From 63b553fcba23a6c4e82975a650dbfdae71cde076 Mon Sep 17 00:00:00 2001 From: s1m0 Date: Fri, 20 Aug 2021 18:12:40 +0200 Subject: [PATCH 1/2] Add detector delegatecall in loop --- slither/detectors/all_detectors.py | 1 + .../statements/delegatecall_in_loop.py | 90 +++++++++++ .../0.4.25/delegatecall_loop.sol | 15 ++ ...ll_loop.sol.0.4.25.DelegatecallInLoop.json | 151 ++++++++++++++++++ .../0.5.16/delegatecall_loop.sol | 15 ++ ...ll_loop.sol.0.5.16.DelegatecallInLoop.json | 151 ++++++++++++++++++ .../0.6.11/delegatecall_loop.sol | 15 ++ ...ll_loop.sol.0.6.11.DelegatecallInLoop.json | 151 ++++++++++++++++++ .../0.7.6/delegatecall_loop.sol | 15 ++ ...all_loop.sol.0.7.6.DelegatecallInLoop.json | 151 ++++++++++++++++++ .../0.8.0/delegatecall_loop.sol | 15 ++ ...all_loop.sol.0.8.0.DelegatecallInLoop.json | 151 ++++++++++++++++++ tests/test_detectors.py | 25 +++ 13 files changed, 946 insertions(+) create mode 100644 slither/detectors/statements/delegatecall_in_loop.py create mode 100644 tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol create mode 100644 tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol.0.4.25.DelegatecallInLoop.json create mode 100644 tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol create mode 100644 tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol.0.5.16.DelegatecallInLoop.json create mode 100644 tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol create mode 100644 tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol.0.6.11.DelegatecallInLoop.json create mode 100644 tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol create mode 100644 tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol.0.7.6.DelegatecallInLoop.json create mode 100644 tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol create mode 100644 tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol.0.8.0.DelegatecallInLoop.json diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index f58aabd032..254df09de0 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -79,6 +79,7 @@ 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 0000000000..0f9bb6d349 --- /dev/null +++ b/slither/detectors/statements/delegatecall_in_loop.py @@ -0,0 +1,90 @@ +from slither.core.cfg.node import NodeType +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.slithir.operations import LowLevelCall + + +def detect_delegatecall_in_loop(contract): + results = [] + for f in contract.functions + contract.modifiers: + if f.is_implemented and f.payable: + delegatecall_in_loop(f.entry_point, False, [], results) + return results + + +def delegatecall_in_loop(node, in_loop, visited, results): + if node in visited: + return + # shared visited + visited.append(node) + + if node.type == NodeType.STARTLOOP: + in_loop = True + elif node.type == NodeType.ENDLOOP: + in_loop = False + + if in_loop: + for ir in node.all_slithir_operations(): + if isinstance(ir, (LowLevelCall)) and ir.function_name == "delegatecall": + results.append(node) + + for son in node.sons: + delegatecall_in_loop(son, in_loop, 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. +It's dangerous because `delegatecall` forward the `msg.value` in case the function called is payable. +""" + + # 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 = """ +Don't use `delegatecall` inside a loop in a payable function or carefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`. +""" + + def _detect(self): + """""" + results = [] + 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 0000000000..4d474454f3 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol @@ -0,0 +1,15 @@ +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; + } + +} \ 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 0000000000..f54670ecc2 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol.0.4.25.DelegatecallInLoop.json @@ -0,0 +1,151 @@ +[ + [ + { + "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": 388, + "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 + ], + "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": 388, + "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 + ], + "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": "High" + } + ] +] \ 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 0000000000..4d474454f3 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol @@ -0,0 +1,15 @@ +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; + } + +} \ 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 0000000000..70bbfab88a --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol.0.5.16.DelegatecallInLoop.json @@ -0,0 +1,151 @@ +[ + [ + { + "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": 388, + "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 + ], + "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": 388, + "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 + ], + "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": "High" + } + ] +] \ 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 0000000000..4d474454f3 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol @@ -0,0 +1,15 @@ +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; + } + +} \ 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 0000000000..ea075b87a8 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol.0.6.11.DelegatecallInLoop.json @@ -0,0 +1,151 @@ +[ + [ + { + "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": 388, + "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 + ], + "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": 388, + "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 + ], + "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": "High" + } + ] +] \ 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 0000000000..4d474454f3 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol @@ -0,0 +1,15 @@ +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; + } + +} \ 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 0000000000..0c5cbeb723 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol.0.7.6.DelegatecallInLoop.json @@ -0,0 +1,151 @@ +[ + [ + { + "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": 388, + "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 + ], + "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": 388, + "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 + ], + "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": "High" + } + ] +] \ 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 0000000000..4d474454f3 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol @@ -0,0 +1,15 @@ +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; + } + +} \ 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 0000000000..9229ad3465 --- /dev/null +++ b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol.0.8.0.DelegatecallInLoop.json @@ -0,0 +1,151 @@ +[ + [ + { + "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": 388, + "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 + ], + "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": 388, + "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 + ], + "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": "High" + } + ] +] \ No newline at end of file diff --git a/tests/test_detectors.py b/tests/test_detectors.py index fadcb02f7c..3fc86f49b5 100644 --- a/tests/test_detectors.py +++ b/tests/test_detectors.py @@ -1144,6 +1144,31 @@ def id_test(test_item: Test): "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" From f026361ad508b6f904a496a76edecaf2a5b98ce0 Mon Sep 17 00:00:00 2001 From: s1m0 Date: Wed, 25 Aug 2021 10:24:59 +0200 Subject: [PATCH 2/2] Multiple improvements --- .../statements/delegatecall_in_loop.py | 51 ++- .../0.4.25/delegatecall_loop.sol | 18 + ...ll_loop.sol.0.4.25.DelegatecallInLoop.json | 416 +++++++++++++++++- .../0.5.16/delegatecall_loop.sol | 18 + ...ll_loop.sol.0.5.16.DelegatecallInLoop.json | 416 +++++++++++++++++- .../0.6.11/delegatecall_loop.sol | 18 + ...ll_loop.sol.0.6.11.DelegatecallInLoop.json | 416 +++++++++++++++++- .../0.7.6/delegatecall_loop.sol | 18 + ...all_loop.sol.0.7.6.DelegatecallInLoop.json | 416 +++++++++++++++++- .../0.8.0/delegatecall_loop.sol | 18 + ...all_loop.sol.0.8.0.DelegatecallInLoop.json | 416 +++++++++++++++++- 11 files changed, 2174 insertions(+), 47 deletions(-) diff --git a/slither/detectors/statements/delegatecall_in_loop.py b/slither/detectors/statements/delegatecall_in_loop.py index 0f9bb6d349..58de0359b6 100644 --- a/slither/detectors/statements/delegatecall_in_loop.py +++ b/slither/detectors/statements/delegatecall_in_loop.py @@ -1,34 +1,44 @@ -from slither.core.cfg.node import NodeType +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 +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): - results = [] - for f in contract.functions + contract.modifiers: +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, False, [], results) + delegatecall_in_loop(f.entry_point, 0, [], results) return results -def delegatecall_in_loop(node, in_loop, visited, 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 = True + in_loop_counter += 1 elif node.type == NodeType.ENDLOOP: - in_loop = False - - if in_loop: - for ir in node.all_slithir_operations(): - if isinstance(ir, (LowLevelCall)) and ir.function_name == "delegatecall": - results.append(node) + 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, visited, results) + delegatecall_in_loop(son, in_loop_counter, visited, results) class DelegatecallInLoop(AbstractDetector): @@ -44,10 +54,7 @@ class DelegatecallInLoop(AbstractDetector): 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. -It's dangerous because `delegatecall` forward the `msg.value` in case the function called is payable. -""" + WIKI_DESCRIPTION = "Detect the use of `delegatecall` inside a loop in a payable function." # region wiki_exploit_scenario WIKI_EXPLOIT_SCENARIO = """ @@ -72,12 +79,12 @@ class DelegatecallInLoop(AbstractDetector): # endregion wiki_exploit_scenario WIKI_RECOMMENDATION = """ -Don't use `delegatecall` inside a loop in a payable function or carefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`. +Carefully check that the function called by `delegatecall` is not payable/doesn't use `msg.value`. """ - def _detect(self): + def _detect(self) -> List[Output]: """""" - results = [] + results: List[Output] = [] for c in self.compilation_unit.contracts_derived: values = detect_delegatecall_in_loop(c) for node in values: diff --git a/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol index 4d474454f3..77e4094587 100644 --- a/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol +++ b/tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol @@ -12,4 +12,22 @@ contract C{ 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 index f54670ecc2..87a7649c66 100644 --- 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 @@ -29,7 +29,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -51,7 +51,25 @@ 13, 14, 15, - 16 + 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 @@ -105,7 +123,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.4.25/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -127,7 +145,25 @@ 13, 14, 15, - 16 + 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 @@ -145,7 +181,377 @@ "id": "e057dff3814f9be2d5eca53fe80f41323b8ed90d20bb1e33600bb4e043c40b66", "check": "delegatecall-loop", "impact": "High", - "confidence": "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 index 4d474454f3..77e4094587 100644 --- a/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol +++ b/tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol @@ -12,4 +12,22 @@ contract C{ 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 index 70bbfab88a..112fdb14bf 100644 --- 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 @@ -29,7 +29,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -51,7 +51,25 @@ 13, 14, 15, - 16 + 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 @@ -105,7 +123,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.5.16/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -127,7 +145,25 @@ 13, 14, 15, - 16 + 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 @@ -145,7 +181,377 @@ "id": "71bad0e6228b341671dd1cc38d74fb727f9bbc5764104298596986d8f4967c02", "check": "delegatecall-loop", "impact": "High", - "confidence": "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 index 4d474454f3..77e4094587 100644 --- a/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol +++ b/tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol @@ -12,4 +12,22 @@ contract C{ 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 index ea075b87a8..a4e0ae28e7 100644 --- 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 @@ -29,7 +29,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -51,7 +51,25 @@ 13, 14, 15, - 16 + 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 @@ -105,7 +123,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.6.11/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -127,7 +145,25 @@ 13, 14, 15, - 16 + 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 @@ -145,7 +181,377 @@ "id": "dfa0a166dfe43235e3fbeab4eadd8b0c7c612cd2fefe3cf281d909129b3b824e", "check": "delegatecall-loop", "impact": "High", - "confidence": "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 index 4d474454f3..77e4094587 100644 --- a/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol +++ b/tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol @@ -12,4 +12,22 @@ contract C{ 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 index 0c5cbeb723..f0e3397efa 100644 --- 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 @@ -29,7 +29,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -51,7 +51,25 @@ 13, 14, 15, - 16 + 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 @@ -105,7 +123,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.7.6/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -127,7 +145,25 @@ 13, 14, 15, - 16 + 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 @@ -145,7 +181,377 @@ "id": "33dd934c565095b28b362765c0c885287aaf87741cf31dae44457268f831b7a4", "check": "delegatecall-loop", "impact": "High", - "confidence": "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 index 4d474454f3..77e4094587 100644 --- a/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol +++ b/tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol @@ -12,4 +12,22 @@ contract C{ 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 index 9229ad3465..2d1d81a846 100644 --- 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 @@ -29,7 +29,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -51,7 +51,25 @@ 13, 14, 15, - 16 + 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 @@ -105,7 +123,7 @@ "name": "C", "source_mapping": { "start": 0, - "length": 388, + "length": 1053, "filename_used": "/GENERIC_PATH", "filename_relative": "tests/detectors/delegatecall-loop/0.8.0/delegatecall_loop.sol", "filename_absolute": "/GENERIC_PATH", @@ -127,7 +145,25 @@ 13, 14, 15, - 16 + 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 @@ -145,7 +181,377 @@ "id": "b810117268c82cb0e2ba1fce4549cef820197f59c877fd5f0701661a0f7bbf47", "check": "delegatecall-loop", "impact": "High", - "confidence": "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