-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Much better overapproximation, and maxBufSize limitation #658
base: main
Are you sure you want to change the base?
Conversation
c45ddbf
to
ae72ba7
Compare
EXTCODESIZE
& CALL
return value when the address is symbolic
EXTCODESIZE
& CALL
return value when the address is symbolicEXTCODESIZE
& CALL
return value when the address is symbolic
f494f38
to
32864e9
Compare
Also improve rewrite rule
422af31
to
7a1dded
Compare
EXTCODESIZE
& CALL
return value when the address is symbolicEXTCODESIZE
& CALL
return value when the address is symbolic
EXTCODESIZE
& CALL
return value when the address is symbolicThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, I don't have any insight into these fallback mechanisms.
My superficial review says this is OK :)
@@ -108,6 +108,8 @@ data Command w | |||
, loopDetectionHeuristic :: w ::: LoopHeuristic <!> "StackBased" <?> "Which heuristic should be used to determine if we are in a loop: StackBased (default) or Naive" | |||
, noDecompose :: w ::: Bool <?> "Don't decompose storage slots into separate arrays" | |||
, maxBranch :: w ::: Int <!> "100" <?> "Max number of branches to explore when encountering a symbolic value (default: 100)" | |||
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contrct(s) being examined" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contrct(s) being examined" | |
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contract(s) being examined" |
@@ -131,6 +133,8 @@ data Command w | |||
, loopDetectionHeuristic :: w ::: LoopHeuristic <!> "StackBased" <?> "Which heuristic should be used to determine if we are in a loop: StackBased (default) or Naive" | |||
, noDecompose :: w ::: Bool <?> "Don't decompose storage slots into separate arrays" | |||
, maxBranch :: w ::: Int <!> "100" <?> "Max number of branches to explore when encountering a symbolic value (default: 100)" | |||
, maxBufSize :: w ::: Int <!> "64" <?> "Maximum size of buffers such as calldata and returndata in exponents of 2 (default: 64, i.e. 2^64 bytes)" | |||
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contrct(s) being examined" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contrct(s) being examined" | |
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contract(s) being examined" |
@@ -184,6 +188,8 @@ data Command w | |||
, maxBranch :: w ::: Int <!> "100" <?> "Max number of branches to explore when encountering a symbolic value (default: 100)" | |||
, numCexFuzz :: w ::: Integer <!> "3" <?> "Number of fuzzing tries to do to generate a counterexample (default: 3)" | |||
, askSmtIterations :: w ::: Integer <!> "1" <?> "Number of times we may revisit a particular branching point before we consult the smt solver to check reachability (default: 1)" | |||
, maxBufSize :: w ::: Int <!> "64" <?> "Maximum size of buffers such as calldata and returndata in exponents of 2 (default: 64, i.e. 2^64 bytes)" | |||
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contrct(s) being examined" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contrct(s) being examined" | |
, promiseNoReent:: w ::: Bool <!> "Promise no reentrancy is possible into the contract(s) being examined" |
Reminder to look into possibilities to avoid the duplication of command line arguments for the different modes.
@@ -1407,16 +1391,18 @@ query q = assign #result $ Just $ HandleEffect (Query q) | |||
runBoth :: RunBoth s -> EVM Symbolic s () | |||
runBoth c = assign #result $ Just $ HandleEffect (RunBoth c) | |||
|
|||
-- | Construct RPC Query and halt execution until resolved | |||
fetchAccount :: VMOps t => Expr EAddr -> (Contract -> EVM t s ()) -> EVM t s () | |||
fetchAccount :: VMOps t => Expr EAddr -> (Contract -> EVM t s ()) -> EVM t s () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fetchAccount :: VMOps t => Expr EAddr -> (Contract -> EVM t s ()) -> EVM t s () | |
fetchAccount :: VMOps t => Expr EAddr -> (Contract -> EVM t s ()) -> EVM t s () |
@@ -228,6 +234,8 @@ main = withUtf8 $ do | |||
, dumpTrace = cmd.trace | |||
, decomposeStorage = Prelude.not cmd.noDecompose | |||
, maxBranch = cmd.maxBranch | |||
, promiseNoReent = cmd.promiseNoReent | |||
, maxBufSize = cmd.maxBufSize |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't 64
the maximum value that makes sense here?
Now user could even pass a larger value no?
Shouldn't we force reasonable value here? Maybe max(64, cmd.maxBufSize)
?
let numQeds = sum $ map (fromEnum . isQed) ret | ||
assertEqualM "number of errors" 0 numErrs | ||
assertEqualM "number of counterexamples" 0 numCexes | ||
assertEqualM "number of qed-s" 1 numQeds |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am a bit confused here.
Because there is no promise of no reentrancy, the exploration ends with the call as partial and the assert
is not visited at all?
Description
This overapproximates and so allows us to move forward with the exploration for:
--promise-no-reent
is given. This is a kind of a hack, where we assume that state is not changed of either us or any other contract, when a CALL is made to an unknown code. This is kinda okay when all important state-changing code is guarded by reentrancy locks.I also refactored the STATICCALL abstraction so it is now much more straightforward, and uses the new generic abstraction system. I think it's a VERY cool now.
I have also added:
--max-buf-size
so we can adjust the maximum buffer size. Default is still 2**64 but a lower one can be set, which can still be "good enough" but we won't get internalError-s for too large buffer Cex-es. The proper solution to this is halving the buffer limit and finding a new Cex, until fixedpoint. But that' s a lot of work, and this is good enough for the moment.Checklist