diff --git a/mythril/analysis/report.py b/mythril/analysis/report.py index 2e2d3425..2e2e04d5 100644 --- a/mythril/analysis/report.py +++ b/mythril/analysis/report.py @@ -22,7 +22,7 @@ class Issue: @property def as_dict(self): - issue = {'title': self.title, 'description':self.description, 'function': self.function, 'type': self.type, 'address': self.address, 'debug': self.debug} + issue = {'title': self.title, 'contract': self.contract, 'description': self.description, 'function': self.function, 'type': self.type, 'address': self.address, 'debug': self.debug} if self.filename and self.lineno: issue['filename'] = self.filename diff --git a/mythril/analysis/solver.py b/mythril/analysis/solver.py index 9e59f831..0f6703e6 100644 --- a/mythril/analysis/solver.py +++ b/mythril/analysis/solver.py @@ -1,6 +1,6 @@ -from z3 import Solver, simplify, sat +from z3 import Solver, simplify, sat, unknown from mythril.exceptions import UnsatError - +import logging def get_model(constraints): s = Solver() @@ -8,13 +8,12 @@ def get_model(constraints): for constraint in constraints: s.add(constraint) - - if (s.check() == sat): - + result = s.check() + if result == sat: return s.model() - - else: - raise UnsatError + elif result == unknown: + logging.info("Timeout encountered while solving expression using z3") + raise UnsatError def pretty_print_model(model): diff --git a/mythril/laser/ethereum/call.py b/mythril/laser/ethereum/call.py index aee2f30c..d94b71bc 100644 --- a/mythril/laser/ethereum/call.py +++ b/mythril/laser/ethereum/call.py @@ -1,8 +1,7 @@ import logging from z3 import BitVec, simplify import mythril.laser.ethereum.util as util -from mythril.laser.ethereum.state import Account -from mythril.laser.ethereum.svm import CalldataType +from mythril.laser.ethereum.state import Account, CalldataType import re """ diff --git a/mythril/laser/ethereum/instructions.py b/mythril/laser/ethereum/instructions.py index f488146e..a73df079 100644 --- a/mythril/laser/ethereum/instructions.py +++ b/mythril/laser/ethereum/instructions.py @@ -158,7 +158,7 @@ class Instruction: result = Concat(BitVecVal(0, 248), Extract(offset + 7, offset, op1)) except AttributeError: logging.debug("BYTE: Unsupported symbolic byte offset") - result = BitVec(str(simplify(op1)) + "_" + str(simplify(op0)), 256) + result = BitVec(str(simplify(op1)) + "[" + str(simplify(op0)) + "]", 256) mstate.stack.append(simplify(result)) return [global_state] @@ -220,7 +220,7 @@ class Instruction: base, exponent = util.pop_bitvec(state), util.pop_bitvec(state) if (type(base) != BitVecNumRef) or (type(exponent) != BitVecNumRef): - state.stack.append(BitVec(str(base) + "_EXP_" + str(exponent), 256)) + state.stack.append(BitVec("(" + str(simplify(base)) + ")^(" + str(simplify(exponent)) + ")", 256)) elif base.as_long() == 2: if exponent.as_long() == 0: state.stack.append(BitVecVal(1, 256)) @@ -331,13 +331,13 @@ class Instruction: b = environment.calldata[offset] except AttributeError: logging.debug("CALLDATALOAD: Unsupported symbolic index") - state.stack.append( - BitVec("calldata_" + str(environment.active_account.contract_name) + "_" + str(op0), 256)) + state.stack.append(BitVec( + "calldata_" + str(environment.active_account.contract_name) + "[" + str(simplify(op0)) + "]", 256)) return [global_state] except IndexError: logging.debug("Calldata not set, using symbolic variable instead") - state.stack.append( - BitVec("calldata_" + str(environment.active_account.contract_name) + "_" + str(op0), 256)) + state.stack.append(BitVec( + "calldata_" + str(environment.active_account.contract_name) + "[" + str(simplify(op0)) + "]", 256)) return [global_state] if type(b) == int: @@ -351,12 +351,12 @@ class Instruction: state.stack.append(BitVecVal(int.from_bytes(val, byteorder='big'), 256)) # FIXME: broad exception catch except: - state.stack.append( - BitVec("calldata_" + str(environment.active_account.contract_name) + "_" + str(op0), 256)) + state.stack.append(BitVec( + "calldata_" + str(environment.active_account.contract_name) + "[" + str(simplify(op0)) + "]", 256)) else: # symbolic variable - state.stack.append( - BitVec("calldata_" + str(environment.active_account.contract_name) + "_" + str(op0), 256)) + state.stack.append(BitVec( + "calldata_" + str(environment.active_account.contract_name) + "[" + str(simplify(op0)) + "]", 256)) return [global_state] @@ -383,24 +383,29 @@ class Instruction: logging.debug("Unsupported symbolic memory offset in CALLDATACOPY") return [global_state] + dstart_sym = False try: dstart = util.get_concrete_int(op1) # FIXME: broad exception catch except: logging.debug("Unsupported symbolic calldata offset in CALLDATACOPY") - state.mem_extend(mstart, 1) - state.memory[mstart] = BitVec("calldata_" + str(environment.active_account.contract_name) + "_cpy", - 256) - return [global_state] + dstart = simplify(op1) + dstart_sym = True + size_sym = False try: size = util.get_concrete_int(op2) # FIXME: broad exception catch except: logging.debug("Unsupported symbolic size in CALLDATACOPY") + size = simplify(op2) + size_sym = True + + if dstart_sym or size_sym: state.mem_extend(mstart, 1) state.memory[mstart] = BitVec( - "calldata_" + str(environment.active_account.contract_name) + "_" + str(dstart), 256) + "calldata_" + str(environment.active_account.contract_name) + "[" + str(dstart) + ": + " + str( + size) + "]", 256) return [global_state] if size > 0: @@ -411,7 +416,8 @@ class Instruction: logging.debug("Memory allocation error: mstart = " + str(mstart) + ", size = " + str(size)) state.mem_extend(mstart, 1) state.memory[mstart] = BitVec( - "calldata_" + str(environment.active_account.contract_name) + "_" + str(dstart), 256) + "calldata_" + str(environment.active_account.contract_name) + "[" + str(dstart) + ": + " + str( + size) + "]", 256) return [global_state] try: @@ -424,7 +430,8 @@ class Instruction: logging.debug("Exception copying calldata to memory") state.memory[mstart] = BitVec( - "calldata_" + str(environment.active_account.contract_name) + "_" + str(dstart), 256) + "calldata_" + str(environment.active_account.contract_name) + "[" + str(dstart) + ": + " + str( + size) + "]", 256) return [global_state] # Environment @@ -475,7 +482,7 @@ class Instruction: # FIXME: broad exception catch except: # Can't access symbolic memory offsets - state.stack.append(BitVec("KECCAC_mem_" + str(op0) + ")", 256)) + state.stack.append(BitVec("KECCAC_mem[" + str(simplify(op0)) + "]", 256)) return [global_state] try: @@ -556,7 +563,7 @@ class Instruction: state = global_state.mstate blocknumber = state.stack.pop() state.stack.append(BitVec("blockhash_block_" + str(blocknumber), 256)) - return global_state + return [global_state] @instruction def coinbase_(self, global_state): @@ -595,14 +602,14 @@ class Instruction: offset = util.get_concrete_int(op0) except AttributeError: logging.debug("Can't MLOAD from symbolic index") - data = BitVec("mem_" + str(op0), 256) + data = BitVec("mem[" + str(simplify(op0)) + "]", 256) state.stack.append(data) return [global_state] try: data = util.concrete_int_from_bytes(state.memory, offset) except IndexError: # Memory slot not allocated - data = BitVec("mem_" + str(offset), 256) + data = BitVec("mem[" + str(offset) + "]", 256) except TypeError: # Symbolic memory data = state.memory[offset] diff --git a/mythril/laser/ethereum/svm.py b/mythril/laser/ethereum/svm.py index 1ceb3740..c7dc2927 100644 --- a/mythril/laser/ethereum/svm.py +++ b/mythril/laser/ethereum/svm.py @@ -4,6 +4,7 @@ from mythril.laser.ethereum.state import GlobalState, Environment, CalldataType, from mythril.laser.ethereum.instructions import Instruction from mythril.laser.ethereum.cfg import NodeFlags, Node, Edge, JumpType from mythril.laser.ethereum.strategy.basic import DepthFirstSearchStrategy +from functools import reduce TT256 = 2 ** 256 TT256M1 = 2 ** 256 - 1 @@ -23,6 +24,7 @@ class LaserEVM: Laser EVM class """ def __init__(self, accounts, dynamic_loader=None, max_depth=22): + self.instructions_covered = [] self.accounts = accounts self.nodes = {} @@ -35,6 +37,9 @@ class LaserEVM: self.strategy = DepthFirstSearchStrategy(self.work_list, max_depth) self.max_depth = max_depth + self.pre_hooks = {} + self.post_hooks = {} + logging.info("LASER EVM initialized with dynamic loader: " + str(dynamic_loader)) def sym_exec(self, main_address): @@ -51,7 +56,8 @@ class LaserEVM: calldata_type=CalldataType.SYMBOLIC, ) - # TODO: contact name fix + self.instructions_covered = [False for _ in environment.code.instruction_list] + initial_node = Node(environment.active_account.contract_name) self.nodes[initial_node.uid] = initial_node @@ -63,6 +69,7 @@ class LaserEVM: self._sym_exec() logging.info("Execution complete") + logging.info("Achieved {0:.3g}% coverage".format(self.coverage)) logging.info("%d nodes, %d edges, %d total states", len(self.nodes), len(self.edges), self.total_states) def _sym_exec(self): @@ -81,7 +88,13 @@ class LaserEVM: def execute_state(self, global_state): instructions = global_state.environment.code.instruction_list op_code = instructions[global_state.mstate.pc]['opcode'] - return Instruction(op_code, self.dynamic_loader).evaluate(global_state), op_code + self.instructions_covered[global_state.mstate.pc] = True + + self._execute_pre_hook(op_code, global_state) + new_global_states = Instruction(op_code, self.dynamic_loader).evaluate(global_state) + self._execute_post_hook(op_code, new_global_states) + + return new_global_states, op_code def manage_cfg(self, opcode, new_states): if opcode == "JUMP": @@ -128,5 +141,42 @@ class LaserEVM: new_node.flags |= NodeFlags.FUNC_ENTRY logging.info("- Entering function " + environment.active_account.contract_name + ":" + new_node.function_name) + elif address == 0: + environment.active_function_name = "fallback" new_node.function_name = environment.active_function_name + + @property + def coverage(self): + return reduce(lambda sum_, val: sum_ + 1 if val else sum_, self.instructions_covered) / float( + len(self.instructions_covered)) * 100 + + def _execute_pre_hook(self, op_code, global_state): + if op_code not in self.pre_hooks.keys(): + return + for hook in self.pre_hooks[op_code]: + hook(global_state) + + def _execute_post_hook(self, op_code, global_states): + if op_code not in self.post_hooks.keys(): + return + + for hook in self.post_hooks[op_code]: + for global_state in global_states: + hook(global_state) + + def hook(self, op_code): + def hook_decorator(function): + if op_code not in self.pre_hooks.keys(): + self.pre_hooks[op_code] = [] + self.pre_hooks[op_code].append(function) + return function + return hook_decorator + + def post_hook(self, op_code): + def hook_decorator(function): + if op_code not in self.post_hooks.keys(): + self.post_hooks[op_code] = [] + self.post_hooks[op_code].append(function) + return function + return hook_decorator diff --git a/requirements.txt b/requirements.txt index aad67f69..c2c8e8a7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ configparser>=3.5.0 coverage eth_abi>=1.0.0 eth-account>=0.1.0a2 -ethereum==2.3.1 +ethereum>=2.3.2 eth-hash>=0.1.0 eth-keyfile>=0.5.1 eth-keys>=0.2.0b3 @@ -19,5 +19,5 @@ pytest>=3.6.0 pytest-cov pytest_mock requests -rlp<1.0.0 +rlp>=1.0.1 z3-solver>=4.5 diff --git a/setup.py b/setup.py index 0e7c624d..e1a623a2 100755 --- a/setup.py +++ b/setup.py @@ -305,7 +305,7 @@ setup( packages=find_packages(exclude=['contrib', 'docs', 'tests']), install_requires=[ - 'ethereum==2.3.1', + 'ethereum>=2.3.2', 'z3-solver>=4.5', 'requests', 'py-solc', @@ -320,7 +320,7 @@ setup( 'eth-tester>=0.1.0b21', 'coverage', 'jinja2>=2.9', - 'rlp<1.0.0', + 'rlp>=1.0.1', 'py-flags', 'mock', 'configparser>=3.5.0', diff --git a/tests/testdata/outputs_expected/calls.sol.o.json b/tests/testdata/outputs_expected/calls.sol.o.json index 3a93166f..5b7e39a9 100644 --- a/tests/testdata/outputs_expected/calls.sol.o.json +++ b/tests/testdata/outputs_expected/calls.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 661, "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0x5a6814ec", "title": "Message call to external contract", "type": "Informational"}, {"address": 666, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x5a6814ec", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 779, "debug": "", "description": "This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `_function_0x2776b163`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xd24b08cc", "title": "Message call to external contract", "type": "Warning"}, {"address": 779, "debug": "", "description": "A possible transaction order independence vulnerability exists in function _function_0xd24b08cc. The value or direction of the call statement is determined from a tainted storage location", "function": "_function_0xd24b08cc", "title": "Transaction order dependence", "type": "Warning"}, {"address": 784, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xd24b08cc", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 858, "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0xe11f493e", "title": "Message call to external contract", "type": "Informational"}, {"address": 869, "debug": "", "description": "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.", "function": "_function_0xe11f493e", "title": "State change after external call", "type": "Warning"}, {"address": 871, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe11f493e", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 912, "debug": "", "description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xe1d10f79", "title": "Message call to external contract", "type": "Warning"}, {"address": 918, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe1d10f79", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 661, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0x5a6814ec", "title": "Message call to external contract", "type": "Informational"}, {"address": 666, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x5a6814ec", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 779, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to an address found at storage slot 1. This storage slot can be written to by calling the function `_function_0x2776b163`. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xd24b08cc", "title": "Message call to external contract", "type": "Warning"}, {"address": 779, "contract": "Unknown", "debug": "", "description": "A possible transaction order independence vulnerability exists in function _function_0xd24b08cc. The value or direction of the call statement is determined from a tainted storage location", "function": "_function_0xd24b08cc", "title": "Transaction order dependence", "type": "Warning"}, {"address": 784, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xd24b08cc", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 858, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0xe11f493e", "title": "Message call to external contract", "type": "Informational"}, {"address": 869, "contract": "Unknown", "debug": "", "description": "The contract account state is changed after an external call. Consider that the called contract could re-enter the function before this state change takes place. This can lead to business logic vulnerabilities.", "function": "_function_0xe11f493e", "title": "State change after external call", "type": "Warning"}, {"address": 871, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe11f493e", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 912, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xe1d10f79", "title": "Message call to external contract", "type": "Warning"}, {"address": 918, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe1d10f79", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/ether_send.sol.o.json b/tests/testdata/outputs_expected/ether_send.sol.o.json index 6d6caad0..d893749f 100644 --- a/tests/testdata/outputs_expected/ether_send.sol.o.json +++ b/tests/testdata/outputs_expected/ether_send.sol.o.json @@ -1,22 +1 @@ -{ - "success": true, - "error": null, - "issues": [ - { - "title": "Ether send", - "description": "In the function `withdrawfunds()` a non-zero amount of Ether is sent to msg.sender.\n\nThere is a check on storage index 1. This storage slot can be written to by calling the function `crowdfunding()`.", - "function": "withdrawfunds()", - "type": "Warning", - "address": 722, - "debug": "" - }, - { - "title": "Integer Overflow", - "description": "A possible integer overflow exists in the function `invest()`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", - "function": "invest()", - "type": "Warning", - "address": 883, - "debug": "" - } - ] -} +{"error": null, "issues": [{"address": 722, "contract": "Unknown", "debug": "", "description": "In the function `withdrawfunds()` a non-zero amount of Ether is sent to msg.sender.\n\nThere is a check on storage index 1. This storage slot can be written to by calling the function `crowdfunding()`.", "function": "withdrawfunds()", "title": "Ether send", "type": "Warning"}, {"address": 883, "contract": "Unknown", "debug": "", "description": "A possible integer overflow exists in the function `invest()`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", "function": "invest()", "title": "Integer Overflow", "type": "Warning"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/exceptions.sol.o.json b/tests/testdata/outputs_expected/exceptions.sol.o.json index 4434c91f..e923bb3a 100644 --- a/tests/testdata/outputs_expected/exceptions.sol.o.json +++ b/tests/testdata/outputs_expected/exceptions.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 446, "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0x546455b5", "title": "Exception state", "type": "Informational"}, {"address": 484, "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0x92dd38ea", "title": "Exception state", "type": "Informational"}, {"address": 506, "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0xa08299f1", "title": "Exception state", "type": "Informational"}, {"address": 531, "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0xb34c3610", "title": "Exception state", "type": "Informational"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 446, "contract": "Unknown", "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0x546455b5", "title": "Exception state", "type": "Informational"}, {"address": 484, "contract": "Unknown", "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0x92dd38ea", "title": "Exception state", "type": "Informational"}, {"address": 506, "contract": "Unknown", "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0xa08299f1", "title": "Exception state", "type": "Informational"}, {"address": 531, "contract": "Unknown", "debug": "", "description": "A reachable exception (opcode 0xfe) has been detected. This can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. This is acceptable in most situations. Note however that `assert()` should only be used to check invariants. Use `require()` for regular input checking. ", "function": "_function_0xb34c3610", "title": "Exception state", "type": "Informational"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/kinds_of_calls.sol.o.json b/tests/testdata/outputs_expected/kinds_of_calls.sol.o.json index 747f1118..ccdf57c0 100644 --- a/tests/testdata/outputs_expected/kinds_of_calls.sol.o.json +++ b/tests/testdata/outputs_expected/kinds_of_calls.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 626, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x141f32ff", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 857, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x9b58bc26", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "debug": "", "description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xeea4c864", "title": "Message call to external contract", "type": "Warning"}, {"address": 1046, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xeea4c864", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 626, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x141f32ff", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 857, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0x9b58bc26", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to an address provided as a function argument. Generally, it is not recommended to call user-supplied addresses using Solidity's call() construct. Note that attackers might leverage reentrancy attacks to exploit race conditions or manipulate this contract's state.", "function": "_function_0xeea4c864", "title": "Message call to external contract", "type": "Warning"}, {"address": 1046, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xeea4c864", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/metacoin.sol.o.json b/tests/testdata/outputs_expected/metacoin.sol.o.json index fd59d519..b0610b5f 100644 --- a/tests/testdata/outputs_expected/metacoin.sol.o.json +++ b/tests/testdata/outputs_expected/metacoin.sol.o.json @@ -1,14 +1 @@ -{ - "success": true, - "error": null, - "issues": [ - { - "title": "Integer Overflow", - "description": "A possible integer overflow exists in the function `sendToken(address,uint256)`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", - "function": "sendToken(address,uint256)", - "type": "Warning", - "address": 498, - "debug": "" - } - ] -} +{"error": null, "issues": [{"address": 498, "contract": "Unknown", "debug": "", "description": "A possible integer overflow exists in the function `sendToken(address,uint256)`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", "function": "sendToken(address,uint256)", "title": "Integer Overflow", "type": "Warning"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/multi_contracts.sol.o.json b/tests/testdata/outputs_expected/multi_contracts.sol.o.json index ff019037..1d4a5e35 100644 --- a/tests/testdata/outputs_expected/multi_contracts.sol.o.json +++ b/tests/testdata/outputs_expected/multi_contracts.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 142, "debug": "", "description": "In the function `_function_0x8a4068dd` a non-zero amount of Ether is sent to msg.sender.\nIt seems that this function can be called without restrictions.", "function": "_function_0x8a4068dd", "title": "Ether send", "type": "Warning"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 142, "contract": "Unknown", "debug": "", "description": "In the function `_function_0x8a4068dd` a non-zero amount of Ether is sent to msg.sender.\nIt seems that this function can be called without restrictions.", "function": "_function_0x8a4068dd", "title": "Ether send", "type": "Warning"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/origin.sol.o.json b/tests/testdata/outputs_expected/origin.sol.o.json index 2024d492..1ac2d554 100644 --- a/tests/testdata/outputs_expected/origin.sol.o.json +++ b/tests/testdata/outputs_expected/origin.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 317, "debug": "", "description": "Function transferOwnership(address) retrieves the transaction origin (tx.origin) using the ORIGIN opcode. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin", "function": "transferOwnership(address)", "title": "Use of tx.origin", "type": "Warning"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 317, "contract": "Unknown", "debug": "", "description": "Function transferOwnership(address) retrieves the transaction origin (tx.origin) using the ORIGIN opcode. Use msg.sender instead.\nSee also: https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin", "function": "transferOwnership(address)", "title": "Use of tx.origin", "type": "Warning"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/overflow.sol.o.json b/tests/testdata/outputs_expected/overflow.sol.o.json index 8345944e..341e5b46 100644 --- a/tests/testdata/outputs_expected/overflow.sol.o.json +++ b/tests/testdata/outputs_expected/overflow.sol.o.json @@ -1,30 +1 @@ -{ - "success": true, - "error": null, - "issues": [ - { - "title": "Integer Underflow", - "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", - "function": "sendeth(address,uint256)", - "type": "Warning", - "address": 649, - "debug": "" - }, - { - "title": "Integer Overflow", - "description": "A possible integer overflow exists in the function `sendeth(address,uint256)`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", - "function": "sendeth(address,uint256)", - "type": "Warning", - "address": 725, - "debug": "" - }, - { - "title": "Integer Underflow", - "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", - "function": "sendeth(address,uint256)", - "type": "Warning", - "address": 567, - "debug": "" - } - ] -} +{"error": null, "issues": [{"address": 567, "contract": "Unknown", "debug": "", "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", "function": "sendeth(address,uint256)", "title": "Integer Underflow", "type": "Warning"}, {"address": 649, "contract": "Unknown", "debug": "", "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", "function": "sendeth(address,uint256)", "title": "Integer Underflow", "type": "Warning"}, {"address": 725, "contract": "Unknown", "debug": "", "description": "A possible integer overflow exists in the function `sendeth(address,uint256)`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", "function": "sendeth(address,uint256)", "title": "Integer Overflow", "type": "Warning"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/returnvalue.sol.o.json b/tests/testdata/outputs_expected/returnvalue.sol.o.json index a3fe1e4c..11ebd735 100644 --- a/tests/testdata/outputs_expected/returnvalue.sol.o.json +++ b/tests/testdata/outputs_expected/returnvalue.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 196, "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0x633ab5e0", "title": "Message call to external contract", "type": "Informational"}, {"address": 285, "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0xe3bea282", "title": "Message call to external contract", "type": "Informational"}, {"address": 290, "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe3bea282", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 196, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0x633ab5e0", "title": "Message call to external contract", "type": "Informational"}, {"address": 285, "contract": "Unknown", "debug": "", "description": "This contract executes a message call to to another contract. Make sure that the called contract is trusted and does not execute user-supplied code.", "function": "_function_0xe3bea282", "title": "Message call to external contract", "type": "Informational"}, {"address": 290, "contract": "Unknown", "debug": "", "description": "The return value of an external call is not checked. Note that execution continue even if the called contract throws.", "function": "_function_0xe3bea282", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/suicide.sol.o.json b/tests/testdata/outputs_expected/suicide.sol.o.json index a8a189b9..1b5818d1 100644 --- a/tests/testdata/outputs_expected/suicide.sol.o.json +++ b/tests/testdata/outputs_expected/suicide.sol.o.json @@ -1 +1 @@ -{"error": null, "issues": [{"address": 146, "debug": "", "description": "The function `_function_0xcbf0b0c0` executes the SUICIDE instruction. The remaining Ether is sent to an address provided as a function argument.\n\nIt seems that this function can be called without restrictions.", "function": "_function_0xcbf0b0c0", "title": "Unchecked SUICIDE", "type": "Warning"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 146, "contract": "Unknown", "debug": "", "description": "The function `_function_0xcbf0b0c0` executes the SUICIDE instruction. The remaining Ether is sent to an address provided as a function argument.\n\nIt seems that this function can be called without restrictions.", "function": "_function_0xcbf0b0c0", "title": "Unchecked SUICIDE", "type": "Warning"}], "success": true} \ No newline at end of file diff --git a/tests/testdata/outputs_expected/underflow.sol.o.json b/tests/testdata/outputs_expected/underflow.sol.o.json index 8345944e..341e5b46 100644 --- a/tests/testdata/outputs_expected/underflow.sol.o.json +++ b/tests/testdata/outputs_expected/underflow.sol.o.json @@ -1,30 +1 @@ -{ - "success": true, - "error": null, - "issues": [ - { - "title": "Integer Underflow", - "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", - "function": "sendeth(address,uint256)", - "type": "Warning", - "address": 649, - "debug": "" - }, - { - "title": "Integer Overflow", - "description": "A possible integer overflow exists in the function `sendeth(address,uint256)`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", - "function": "sendeth(address,uint256)", - "type": "Warning", - "address": 725, - "debug": "" - }, - { - "title": "Integer Underflow", - "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", - "function": "sendeth(address,uint256)", - "type": "Warning", - "address": 567, - "debug": "" - } - ] -} +{"error": null, "issues": [{"address": 567, "contract": "Unknown", "debug": "", "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", "function": "sendeth(address,uint256)", "title": "Integer Underflow", "type": "Warning"}, {"address": 649, "contract": "Unknown", "debug": "", "description": "A possible integer underflow exists in the function `sendeth(address,uint256)`.\nThe subtraction may result in a value < 0.", "function": "sendeth(address,uint256)", "title": "Integer Underflow", "type": "Warning"}, {"address": 725, "contract": "Unknown", "debug": "", "description": "A possible integer overflow exists in the function `sendeth(address,uint256)`.\nThe addition or multiplication may result in a value higher than the maximum representable integer.", "function": "sendeth(address,uint256)", "title": "Integer Overflow", "type": "Warning"}], "success": true} \ No newline at end of file