From 04ff85fd654d176b5b5cd3e2bab43c1c57ce8fc4 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 28 Feb 2024 17:58:10 -0600 Subject: [PATCH] make it interprocedural (only 1 call deep) --- slither/detectors/all_detectors.py | 2 -- .../functions/out_of_order_retryable.py | 17 ++++++++++--- ...e_0_8_20_out_of_order_retryable_sol__0.txt | 4 +++ .../0.8.20/out_of_order_retryable.sol | 23 ++++++++++++++++++ .../out_of_order_retryable.sol-0.8.20.zip | Bin 5285 -> 5942 bytes 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index fc33ddfd3..4151759f0 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -97,6 +97,4 @@ from .assembly.return_instead_of_leave import ReturnInsteadOfLeave from .operations.incorrect_exp import IncorrectOperatorExponentiation from .statements.tautological_compare import TautologicalCompare from .statements.return_bomb import ReturnBomb - - from .functions.out_of_order_retryable import OutOfOrderRetryable diff --git a/slither/detectors/functions/out_of_order_retryable.py b/slither/detectors/functions/out_of_order_retryable.py index b273052fe..f483dc64a 100644 --- a/slither/detectors/functions/out_of_order_retryable.py +++ b/slither/detectors/functions/out_of_order_retryable.py @@ -98,12 +98,23 @@ Bob calls `doStuffOnL2` but the first retryable ticket calling `claim_rewards` f if self.key not in node.context: node.context[self.key] = fathers_context - # analyze node - for ir in node.irs: + # include ops from internal function calls + internal_ops = [] + for internal_call in node.internal_calls: + if isinstance(internal_call, Function): + internal_ops += internal_call.all_slithir_operations() + + # analyze node for retryable tickets + for ir in node.irs + internal_ops: if ( isinstance(ir, HighLevelCall) and isinstance(ir.function, Function) - and ir.function.name == "createRetryableTicket" + and ir.function.name + in [ + "createRetryableTicket", + "outboundTransferCustomRefund", + "unsafeCreateRetryableTicket", + ] ): node.context[self.key].append(node) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt index 4f07601b1..a54b2240d 100644 --- a/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt +++ b/tests/e2e/detectors/snapshots/detectors__detector_OutOfOrderRetryable_0_8_20_out_of_order_retryable_sol__0.txt @@ -6,3 +6,7 @@ Multiple retryable tickets created in the same function: -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#40-48) -Y(msg.sender).createRetryableTicket(address(2),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#50-58) +Multiple retryable tickets created in the same function: + -Y(msg.sender).createRetryableTicket(address(1),0,0,address(0),address(0),0,0,) (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#83-91) + -good2() (tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol#92) + diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol index afd4d274b..af20814a5 100644 --- a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol +++ b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol @@ -79,4 +79,27 @@ function bad2() external { 0, ""); } +function bad3() external { + Y(msg.sender).createRetryableTicket( + address(1), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); + good2(); +} +function good2() internal { + Y(msg.sender).createRetryableTicket( + address(2), + 0, + 0, + address(0), + address(0), + 0, + 0, + ""); +} } \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip b/tests/e2e/detectors/test_data/out-of-order-retryable/0.8.20/out_of_order_retryable.sol-0.8.20.zip index 1baadba84d201e0a4cecf23dae4f0c2af3f8445c..604b64ae7a38a632dcaeafeae1bc773299210399 100644 GIT binary patch delta 5662 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 S004#slin6m1~U`@0000~g^O?i