diff --git a/mythril/analysis/modules/deprecated_ops.py b/mythril/analysis/modules/deprecated_ops.py index ea07b3ab..e8dc22aa 100644 --- a/mythril/analysis/modules/deprecated_ops.py +++ b/mythril/analysis/modules/deprecated_ops.py @@ -1,64 +1,72 @@ from mythril.analysis.report import Issue -from mythril.analysis.swc_data import TX_ORIGIN_USAGE +from mythril.analysis.swc_data import DEPRICATED_FUNCTIONS_USAGE from mythril.analysis.modules.base import DetectionModule +from mythril.laser.ethereum.state.global_state import GlobalState import logging +DESCRIPTION = """ +Check for usage of deprecated opcodes """ -MODULE DESCRIPTION: -Check for constraints on tx.origin (i.e., access to some functionality is restricted to a specific origin). -""" + +def _analyze_state(state): + node = state.node + instruction = state.get_current_instruction() + + if instruction["opcode"] == "ORIGIN": + logging.debug("ORIGIN in function " + node.function_name) + title = "Use of tx.origin" + description = ( + "The function `{}` 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".format( + node.function_name + ) + ) + swc_id = DEPRICATED_FUNCTIONS_USAGE + + elif instruction["opcode"] == "CALLCODE": + logging.debug("CALLCODE in function " + node.function_name) + title = "Use of callcode" + description = ( + "The function `{}` uses callcode. Callcode does not persist sender or value over the call. " + "Use delegatecall instead.".format(node.function_name) + ) + swc_id = DEPRICATED_FUNCTIONS_USAGE + + issue = Issue( + contract=node.contract_name, + function_name=node.function_name, + address=instruction["address"], + title=title, + bytecode=state.environment.code.bytecode, + _type="Warning", + swc_id=swc_id, + description=description, + gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used), + ) + return [issue] class DeprecatedOperationsModule(DetectionModule): def __init__(self): super().__init__( name="Deprecated Operations", - swc_id=TX_ORIGIN_USAGE, - hooks=["ORIGIN"], - description=( - "Check for constraints on tx.origin (i.e., access to some " - "functionality is restricted to a specific origin)." - ), + swc_id=DEPRICATED_FUNCTIONS_USAGE, + hooks=["ORIGIN", "CALLCODE"], + description=(DESCRIPTION), + entrypoint="callback", ) + self._issues = [] - def execute(self, statespace): - - logging.debug("Executing module: DEPRECATED OPCODES") - - issues = [] - - for k in statespace.nodes: - node = statespace.nodes[k] - - for state in node.states: - - instruction = state.get_current_instruction() - - if instruction["opcode"] == "ORIGIN": - description = ( - "The function `{}` 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".format( - node.function_name - ) - ) - - issue = Issue( - contract=node.contract_name, - function_name=node.function_name, - address=instruction["address"], - title="Use of tx.origin", - bytecode=state.environment.code.bytecode, - _type="Warning", - swc_id=TX_ORIGIN_USAGE, - description=description, - gas_used=(state.mstate.min_gas_used, state.mstate.max_gas_used), - ) - issues.append(issue) + def execute(self, state: GlobalState): + self._issues.extend(_analyze_state(state)) + return self.issues - return issues + @property + def issues(self): + return self._issues detector = DeprecatedOperationsModule() 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 33da5788..bd4d3c7d 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, "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", "max_gas_used": 35856, "min_gas_used": 1104, "swc-id": "104", "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", "max_gas_used": 35919, "min_gas_used": 1167, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "_function_0xeea4c864", "max_gas_used": 1229, "min_gas_used": 477, "swc-id": "107", "title": "External call to user-supplied address", "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", "max_gas_used": 35944, "min_gas_used": 1192, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} \ No newline at end of file +{"error": null, "issues": [{"address": 618, "contract": "Unknown", "debug": "", "description": "The function `_function_0x141f32ff` uses callcode. Callcode does not persist sender or value over the call. Use delegatecall instead.", "function": "_function_0x141f32ff", "max_gas_used": 1141, "min_gas_used": 389, "swc-id": "111", "title": "Use of callcode", "type": "Warning"}, {"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", "max_gas_used": 35856, "min_gas_used": 1104, "swc-id": "104", "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", "max_gas_used": 35919, "min_gas_used": 1167, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}, {"address": 1038, "contract": "Unknown", "debug": "", "description": "The contract executes a function call with high gas to a user-supplied address. Note that the callee can contain arbitrary code and may re-enter any function in this contract. Review the business logic carefully to prevent unanticipated effects on the contract state.", "function": "_function_0xeea4c864", "max_gas_used": 1229, "min_gas_used": 477, "swc-id": "107", "title": "External call to user-supplied address", "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", "max_gas_used": 35944, "min_gas_used": 1192, "swc-id": "104", "title": "Unchecked CALL return value", "type": "Informational"}], "success": true} diff --git a/tests/testdata/outputs_expected/kinds_of_calls.sol.o.markdown b/tests/testdata/outputs_expected/kinds_of_calls.sol.o.markdown index d3fb63bf..2dba3288 100644 --- a/tests/testdata/outputs_expected/kinds_of_calls.sol.o.markdown +++ b/tests/testdata/outputs_expected/kinds_of_calls.sol.o.markdown @@ -1,5 +1,17 @@ # Analysis results for test-filename.sol +## Use of callcode +- SWC ID: 111 +- Type: Warning +- Contract: Unknown +- Function name: `_function_0x141f32ff` +- PC address: 618 +- Estimated Gas Usage: 389 - 1141 + +### Description + +The function `_function_0x141f32ff` uses callcode. Callcode does not persist sender or value over the call. Use delegatecall instead. + ## Unchecked CALL return value - SWC ID: 104 - Type: Informational diff --git a/tests/testdata/outputs_expected/kinds_of_calls.sol.o.text b/tests/testdata/outputs_expected/kinds_of_calls.sol.o.text index 1f244935..3a1ba9fb 100644 --- a/tests/testdata/outputs_expected/kinds_of_calls.sol.o.text +++ b/tests/testdata/outputs_expected/kinds_of_calls.sol.o.text @@ -1,3 +1,13 @@ +==== Use of callcode ==== +SWC ID: 111 +Type: Warning +Contract: Unknown +Function name: _function_0x141f32ff +PC address: 618 +Estimated Gas Usage: 389 - 1141 +The function `_function_0x141f32ff` uses callcode. Callcode does not persist sender or value over the call. Use delegatecall instead. +-------------------- + ==== Unchecked CALL return value ==== SWC ID: 104 Type: Informational diff --git a/tests/testdata/outputs_expected/origin.sol.o.json b/tests/testdata/outputs_expected/origin.sol.o.json index 49a3d6b1..11a5212c 100644 --- a/tests/testdata/outputs_expected/origin.sol.o.json +++ b/tests/testdata/outputs_expected/origin.sol.o.json @@ -9,7 +9,7 @@ "function": "transferOwnership(address)", "max_gas_used": 1051, "min_gas_used": 626, - "swc-id": "115", + "swc-id": "111", "title": "Use of tx.origin", "type": "Warning" } diff --git a/tests/testdata/outputs_expected/origin.sol.o.markdown b/tests/testdata/outputs_expected/origin.sol.o.markdown index 07b2d60e..1e0ad30c 100644 --- a/tests/testdata/outputs_expected/origin.sol.o.markdown +++ b/tests/testdata/outputs_expected/origin.sol.o.markdown @@ -1,7 +1,7 @@ # Analysis results for test-filename.sol ## Use of tx.origin -- SWC ID: 115 +- SWC ID: 111 - Type: Warning - Contract: Unknown - Function name: `transferOwnership(address)` diff --git a/tests/testdata/outputs_expected/origin.sol.o.text b/tests/testdata/outputs_expected/origin.sol.o.text index 919d1f18..acf08a93 100644 --- a/tests/testdata/outputs_expected/origin.sol.o.text +++ b/tests/testdata/outputs_expected/origin.sol.o.text @@ -1,5 +1,5 @@ ==== Use of tx.origin ==== -SWC ID: 115 +SWC ID: 111 Type: Warning Contract: Unknown Function name: transferOwnership(address)