-
Notifications
You must be signed in to change notification settings - Fork 6.3k
[SMTChecker] Report contract invariants #11451
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
Conversation
test/libsolidity/smtCheckerTests/array_members/length_same_after_assignment_2.sol
Outdated
Show resolved
Hide resolved
a0c8df3 to
360d86a
Compare
|
I checked most of the tests and they are looking good. I am reviewing implementation now |
|
We only briefly talked in the chat, should talk about that in the design call today. |
mijovic
left a comment
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.
Only first small comments.
I am doing another turn now
360d86a to
2b0f519
Compare
2b0f519 to
7570c3c
Compare
|
Test |
e67ed7a to
8f1645b
Compare
8f1645b to
e2588a5
Compare
|
This is now ready for review |
4a653bf to
41838a7
Compare
test/libsolidity/smtCheckerTests/array_members/length_1d_copy_2d_storage_to_memory.sol
Show resolved
Hide resolved
test/libsolidity/smtCheckerTests/array_members/length_1d_struct_array_1.sol
Show resolved
Hide resolved
| (x <= 0) | ||
| Reentrancy property(ies) for model_checker_invariants_contract_reentrancy/input.sol:test: | ||
| (!(x <= 0) || (x' <= 0)) | ||
| ((!(x <= 0) || !(<errorCode> >= 3)) && (!(x <= 0) || (x' <= 0))) |
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.
What's errorCode?
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.
Yea maybe we need to either change that or explain it a bit more. Every verification target (assertion, out of bounds, etc) gets a unique non-zero errorCode starting at one. So if errorCode = 0, all good. If errorCode > 0, something failed, but we're not saying here exactly what failed. Do you have a suggestion for how to handle it?
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.
Actually what does !(errorCode >= 3) mean here? The failure is one of the three {assertion, out of bounds, ...}.
Maybe it would be nice to print a table of error codes. It would be even better if we can change !(<errorCode> >= 3) to just a list of possibilities.
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.
No, the number is not per target type, it's per query, basically.
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 think it would be better to leave it is as for the moment, and try to explain what it means, and adjust it later. I don't have a clear answer about what's best for this now, so I'd prefer not to stall this PR and do it after.
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.
Hmm maybe listing all targets if errorCode is present is not too hard to do
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.
Or this @hrkrshnn
41838a7 to
e55b71d
Compare
| return type; | ||
|
|
||
| return _args.at(0) + "." + type; | ||
| } |
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'm going to assume this function is correct :)
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 can argue for its correctness in a call if you want, but yea, I think it's also not too bad if it's buggy, since this is non essential extra information.
| (x <= 0) | ||
| Reentrancy property(ies) for model_checker_invariants_contract_reentrancy/input.sol:test: | ||
| (!(x <= 0) || (x' <= 0)) | ||
| ((!(x <= 0) || !(<errorCode> >= 3)) && (!(x <= 0) || (x' <= 0))) |
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.
Actually what does !(errorCode >= 3) mean here? The failure is one of the three {assertion, out of bounds, ...}.
Maybe it would be nice to print a table of error codes. It would be even better if we can change !(<errorCode> >= 3) to just a list of possibilities.
test/libsolidity/SMTCheckerTest.cpp
Outdated
|
|
||
| if (m_ignoreInv) | ||
| ranges::actions::remove_if(m_errorList, [](auto&& _error) { | ||
| return _error.errorId && _error.errorId->error != 1180; |
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 it possible to avoid creating this in the first place?
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.
Yea, probably better.
4399bcb to
b72aabf
Compare
830576f to
428bab6
Compare
|
@hrkrshnn I fixed the latest comments in new commits, will |
cameel
left a comment
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 haven't reviewed all of it yet but so far I haven't found anything important. Just minor stuff.
libsmtutil/Z3Interface.cpp
Outdated
| else if (kind == Z3_OP_INT2BV) | ||
| smtAssert(false, ""); | ||
| return Expression::int2bv(arguments[0], _expr.get_sort().bv_size()); | ||
| else if (kind == Z3_OP_BV2INT) | ||
| smtAssert(false, ""); | ||
| // TODO manually wrap the result with a check whether the number | ||
| // is positive or negative somehow. | ||
| return Expression::bv2int(arguments[0]); | ||
| else if (kind == Z3_OP_EXTRACT) | ||
| return Expression("extract", {arguments[0]. arguments[1]}, arguments[0].sort); |
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.
What about the number of arguments here? Can there be more than 1 or 2? I think we need asserts against that.
And for Z3_OP_EXTRACT, do sorts have to be the same?
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.
Good point. Extract is actually quite complex since it creates a new function for bitvectors of different sizes, so I'm just gonna do the same as dt_accessor and use all arguments with that operator's name. We can give it some interpretation if we ever handle it properly on the way from z3 to our representation.
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.
ok. What about Z3_OP_BV2INT and Z3_OP_INT2BV though?
test/cmdlineTests/standard_model_checker_invariants_wrong_type_2/input.json
Show resolved
Hide resolved
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.
Looks good. We agreed that this can be more or less merged and the additional changes can be done in follow up PR. Probably missing fixups.
428bab6 to
f193e76
Compare
|
Unfortunately I did not manage to finish the review today but so far I did not find anything that would look like an actual problem so if @hrkrshnn approves then I guess it should be fine to merge it. |
f193e76 to
ac8bf8c
Compare
…a Solidity-like expression string
…the given predicates
|
@hrkrshnn merge merge? |
ac8bf8c to
902a2e2
Compare
Fixes #10787
Spacer already gives invariants for every predicate when the result of a query is unsat, that's the interpretation of each predicate.
If we take those expressions for our
interface_*andnondet_interface_*predicates, we have respectively, contract invariants (over a state) and reentrancy properties (over a transition).So what we do here is
z3::exprthat represents the invariants (a big conjunction)smtutil::ExpressionOpen questions:
TODO:
abifunctions better #11463existsinsideforallproperly, with a stack of substitution maps and shadowing (this is just a note to self) [SMTChecker] Contract invariants - support nested quantifiers #11462Future:
The expressions can of course be simplified to transform things like
a * (- 1)into-aamong others, but that should go into a different PR.