diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index f58aabd03..254df09de 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -79,6 +79,7 @@ from .statements.unary import IncorrectUnaryExpressionDetection from .operations.missing_zero_address_validation import MissingZeroAddressValidation from .functions.dead_code import DeadCode from .statements.write_after_write import WriteAfterWrite +from .statements.delegatecall_in_loop import DelegatecallInLoop # # diff --git a/slither/detectors/statements/delegatecall_in_loop.py b/slither/detectors/statements/delegatecall_in_loop.py new file mode 100644 index 000000000..58de0359b --- /dev/null +++ b/slither/detectors/statements/delegatecall_in_loop.py @@ -0,0 +1,97 @@ +from typing import List +from slither.core.cfg.node import NodeType, Node +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.slithir.operations import LowLevelCall, InternalCall +from slither.core.declarations import Contract +from slither.utils.output import Output + + +def detect_delegatecall_in_loop(contract: Contract) -> List[Node]: + results: List[Node] = [] + for f in contract.functions_entry_points: + if f.is_implemented and f.payable: + delegatecall_in_loop(f.entry_point, 0, [], results) + return results + + +def delegatecall_in_loop( + node: Node, in_loop_counter: int, visited: List[Node], results: List[Node] +) -> None: + if node in visited: + return + # shared visited + visited.append(node) + + if node.type == NodeType.STARTLOOP: + in_loop_counter += 1 + elif node.type == NodeType.ENDLOOP: + in_loop_counter -= 1 + + for ir in node.all_slithir_operations(): + if ( + in_loop_counter > 0 + and isinstance(ir, (LowLevelCall)) + and ir.function_name == "delegatecall" + ): + results.append(ir.node) + if isinstance(ir, (InternalCall)): + delegatecall_in_loop(ir.function.entry_point, in_loop_counter, visited, results) + + for son in node.sons: + delegatecall_in_loop(son, in_loop_counter, visited, results) + + +class DelegatecallInLoop(AbstractDetector): + """ + Detect the use of delegatecall inside a loop in a payable function + """ + + ARGUMENT = "delegatecall-loop" + HELP = "Payable functions using `delegatecall` inside a loop" + IMPACT = DetectorClassification.HIGH + CONFIDENCE = DetectorClassification.MEDIUM + + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop" + + WIKI_TITLE = "Payable functions using `delegatecall` inside a loop" + WIKI_DESCRIPTION = "Detect the use of `delegatecall` inside a loop in a payable function." + + # region wiki_exploit_scenario + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract DelegatecallInLoop{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + +} +``` +When calling `bad` the same `msg.value` amount will be accredited multiple times.""" + # endregion wiki_exploit_scenario + + WIKI_RECOMMENDATION = """ +Carefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`. +""" + + def _detect(self) -> List[Output]: + """""" + results: List[Output] = [] + for c in self.compilation_unit.contracts_derived: + values = detect_delegatecall_in_loop(c) + for node in values: + func = node.function + + info = [func, " has delegatecall inside a loop in a payable function: ", node, "\n"] + res = self.generate_result(info) + results.append(res) + + return results diff --git a/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol new file mode 100644 index 000000000..77e409458 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol @@ -0,0 +1,33 @@ +contract C{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + + function bad2(address[] memory receivers) public payable { + bad2_internal(receivers); + } + + function bad2_internal(address[] memory receivers) internal { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function bad3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + for (uint256 j = 0; j < receivers.length; j++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + } + +} \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol.0.4.25.DelegatecallInLoop.json b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol.0.4.25.DelegatecallInLoop.json new file mode 100644 index 000000000..87a7649c6 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol.0.4.25.DelegatecallInLoop.json @@ -0,0 +1,557 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 188, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + } + } + } + ], + "description": "C.bad(address[]) (tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#5-9) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#7)\n", + "markdown": "[C.bad(address[])](tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L5-L9) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L7)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L5-L9", + "id": "e057dff3814f9be2d5eca53fe80f41323b8ed90d20bb1e33600bb4e043c40b66", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 627, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 21 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + } + } + } + ], + "description": "C.bad2_internal(address[]) (tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#19-23) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#21)\n", + "markdown": "[C.bad2_internal(address[])](tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L19-L23) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L21)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L19-L23", + "id": "95c9b72aff8332665e8e4f528a844ef21bc09ec277d5d27d97c2f0f1d69e8ba3", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 931, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 28 + ], + "starting_column": 17, + "ending_column": 105 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + } + } + } + ], + "description": "C.bad3(address[]) (tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#25-31) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#28)\n", + "markdown": "[C.bad3(address[])](tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L25-L31) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L28)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol#L25-L31", + "id": "77dda07eb6e2fe62ccfc45730422fa556ee775c1f6686148258f1ccc76c86491", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol new file mode 100644 index 000000000..77e409458 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol @@ -0,0 +1,33 @@ +contract C{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + + function bad2(address[] memory receivers) public payable { + bad2_internal(receivers); + } + + function bad2_internal(address[] memory receivers) internal { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function bad3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + for (uint256 j = 0; j < receivers.length; j++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + } + +} \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol.0.5.16.DelegatecallInLoop.json b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol.0.5.16.DelegatecallInLoop.json new file mode 100644 index 000000000..112fdb14b --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol.0.5.16.DelegatecallInLoop.json @@ -0,0 +1,557 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 188, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + } + } + } + ], + "description": "C.bad(address[]) (tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#5-9) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#7)\n", + "markdown": "[C.bad(address[])](tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L5-L9) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L7)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L5-L9", + "id": "71bad0e6228b341671dd1cc38d74fb727f9bbc5764104298596986d8f4967c02", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 627, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 21 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + } + } + } + ], + "description": "C.bad2_internal(address[]) (tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#19-23) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#21)\n", + "markdown": "[C.bad2_internal(address[])](tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L19-L23) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L21)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L19-L23", + "id": "7edbf79d9613bc9338f4956841c0fbece80b489971f8c05ae818babc7e27931a", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 931, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 28 + ], + "starting_column": 17, + "ending_column": 105 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + } + } + } + ], + "description": "C.bad3(address[]) (tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#25-31) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#28)\n", + "markdown": "[C.bad3(address[])](tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L25-L31) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L28)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol#L25-L31", + "id": "e4ea7a031f3f945111f70123e85c9f92b52ac8fd7c04a8c2443393592982e39a", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol new file mode 100644 index 000000000..77e409458 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol @@ -0,0 +1,33 @@ +contract C{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + + function bad2(address[] memory receivers) public payable { + bad2_internal(receivers); + } + + function bad2_internal(address[] memory receivers) internal { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function bad3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + for (uint256 j = 0; j < receivers.length; j++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + } + +} \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol.0.6.11.DelegatecallInLoop.json b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol.0.6.11.DelegatecallInLoop.json new file mode 100644 index 000000000..a4e0ae28e --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol.0.6.11.DelegatecallInLoop.json @@ -0,0 +1,557 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 188, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + } + } + } + ], + "description": "C.bad(address[]) (tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#5-9) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#7)\n", + "markdown": "[C.bad(address[])](tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L5-L9) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L7)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L5-L9", + "id": "dfa0a166dfe43235e3fbeab4eadd8b0c7c612cd2fefe3cf281d909129b3b824e", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 627, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 21 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + } + } + } + ], + "description": "C.bad2_internal(address[]) (tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#19-23) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#21)\n", + "markdown": "[C.bad2_internal(address[])](tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L19-L23) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L21)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L19-L23", + "id": "50e1b9196dcf1e1d7678184956c7a9d3ba470ab23d7be04163d366b092e2df41", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 931, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 28 + ], + "starting_column": 17, + "ending_column": 105 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + } + } + } + ], + "description": "C.bad3(address[]) (tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#25-31) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#28)\n", + "markdown": "[C.bad3(address[])](tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L25-L31) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L28)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol#L25-L31", + "id": "f42b54838c6756ddd38ad98fb9243413bbbd169a6d513737c1b85bd6dc263107", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol new file mode 100644 index 000000000..77e409458 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol @@ -0,0 +1,33 @@ +contract C{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + + function bad2(address[] memory receivers) public payable { + bad2_internal(receivers); + } + + function bad2_internal(address[] memory receivers) internal { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function bad3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + for (uint256 j = 0; j < receivers.length; j++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + } + +} \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol.0.7.6.DelegatecallInLoop.json b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol.0.7.6.DelegatecallInLoop.json new file mode 100644 index 000000000..f0e3397ef --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol.0.7.6.DelegatecallInLoop.json @@ -0,0 +1,557 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 188, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + } + } + } + ], + "description": "C.bad(address[]) (tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#5-9) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#7)\n", + "markdown": "[C.bad(address[])](tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L5-L9) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L7)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L5-L9", + "id": "33dd934c565095b28b362765c0c885287aaf87741cf31dae44457268f831b7a4", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 627, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 21 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + } + } + } + ], + "description": "C.bad2_internal(address[]) (tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#19-23) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#21)\n", + "markdown": "[C.bad2_internal(address[])](tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L19-L23) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L21)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L19-L23", + "id": "a7f58e5431f4817c8f3e39d7efdb1b1633316d9be3fd73669e509ec33b6bd2d3", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 931, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 28 + ], + "starting_column": 17, + "ending_column": 105 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + } + } + } + ], + "description": "C.bad3(address[]) (tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#25-31) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#28)\n", + "markdown": "[C.bad3(address[])](tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L25-L31) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L28)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol#L25-L31", + "id": "40cecf9f87caeb930a800e6eb9c668fd6ca5077af3176e48af13c4892bcaf419", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol new file mode 100644 index 000000000..77e409458 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol @@ -0,0 +1,33 @@ +contract C{ + + mapping (address => uint256) balances; + + function bad(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function addBalance(address a) public payable { + balances[a] += msg.value; + } + + function bad2(address[] memory receivers) public payable { + bad2_internal(receivers); + } + + function bad2_internal(address[] memory receivers) internal { + for (uint256 i = 0; i < receivers.length; i++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + + function bad3(address[] memory receivers) public payable { + for (uint256 i = 0; i < receivers.length; i++) { + for (uint256 j = 0; j < receivers.length; j++) { + address(this).delegatecall(abi.encodeWithSignature("addBalance(address)", receivers[i])); + } + } + } + +} \ No newline at end of file diff --git a/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol.0.8.0.DelegatecallInLoop.json b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol.0.8.0.DelegatecallInLoop.json new file mode 100644 index 000000000..2d1d81a84 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol.0.8.0.DelegatecallInLoop.json @@ -0,0 +1,557 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 188, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 7 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad", + "source_mapping": { + "start": 61, + "length": 232, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 5, + 6, + 7, + 8, + 9 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad(address[])" + } + } + } + } + ], + "description": "C.bad(address[]) (tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#5-9) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#7)\n", + "markdown": "[C.bad(address[])](tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L5-L9) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L7)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L5-L9", + "id": "b810117268c82cb0e2ba1fce4549cef820197f59c877fd5f0701661a0f7bbf47", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 627, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 21 + ], + "starting_column": 13, + "ending_column": 101 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad2_internal", + "source_mapping": { + "start": 496, + "length": 236, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 19, + 20, + 21, + 22, + 23 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad2_internal(address[])" + } + } + } + } + ], + "description": "C.bad2_internal(address[]) (tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#19-23) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#21)\n", + "markdown": "[C.bad2_internal(address[])](tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L19-L23) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L21)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L19-L23", + "id": "c09bee70334dcac1e61b8295e12f2928ec522c8a0682f6068e6c283361ab1e59", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + }, + { + "elements": [ + { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + }, + { + "type": "node", + "name": "address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))", + "source_mapping": { + "start": 931, + "length": 88, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 28 + ], + "starting_column": 17, + "ending_column": 105 + }, + "type_specific_fields": { + "parent": { + "type": "function", + "name": "bad3", + "source_mapping": { + "start": 738, + "length": 312, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "C", + "source_mapping": { + "start": 0, + "length": 1053, + "filename_used": "/GENERIC_PATH", + "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", + "is_dependency": false, + "lines": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34 + ], + "starting_column": 1, + "ending_column": 0 + } + }, + "signature": "bad3(address[])" + } + } + } + } + ], + "description": "C.bad3(address[]) (tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#25-31) has delegatecall inside a loop in a payable function: address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i])) (tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#28)\n", + "markdown": "[C.bad3(address[])](tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L25-L31) has delegatecall inside a loop in a payable function: [address(this).delegatecall(abi.encodeWithSignature(addBalance(address),receivers[i]))](tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L28)\n", + "first_markdown_element": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol#L25-L31", + "id": "0bacdb8b28979c680bd97f07b6a7e17d687dde34b125b23d9d71514d37d5e863", + "check": "delegatecall-loop", + "impact": "High", + "confidence": "Medium" + } + ] +] \ No newline at end of file diff --git a/tests/test_detectors.py b/tests/test_detectors.py index fd82cf0db..dd65f4f9e 100644 --- a/tests/test_detectors.py +++ b/tests/test_detectors.py @@ -1149,6 +1149,31 @@ ALL_TESTS = [ "write-after-write.sol", "0.8.0", ), + Test( + all_detectors.DelegatecallInLoop, + "delegatecall_loop.sol", + "0.4.25", + ), + Test( + all_detectors.DelegatecallInLoop, + "delegatecall_loop.sol", + "0.5.16", + ), + Test( + all_detectors.DelegatecallInLoop, + "delegatecall_loop.sol", + "0.6.11", + ), + Test( + all_detectors.DelegatecallInLoop, + "delegatecall_loop.sol", + "0.7.6", + ), + Test( + all_detectors.DelegatecallInLoop, + "delegatecall_loop.sol", + "0.8.0", + ), ] GENERIC_PATH = "/GENERIC_PATH"