-
Notifications
You must be signed in to change notification settings - Fork 63
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
Catch and handle gracefully when concrete evaluation produces an error #1903
Conversation
6ee6248
to
99cd05c
Compare
…d term instead of throwing an error during setup phase. This fixes the problem that `primitive` values cause failure in concrete evaluation.
99cd05c
to
04e3fb6
Compare
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.
Hi @pennyannn!
Can you explain the motivation behind this PR a bit further? In particular, what specific problem is this patch addressing? Do you have a test case that shows SAW doing something wrong that is corrected by this patch?
Hi @RyanGlScott Here's a small example showing the problem. primitive.c
Primitive.cry
primitive.saw
run.sh
Run
|
Thanks @pennyannn, that's very helpful context. Before getting into the particulars of this PR, it might be helpful to go over why this particular SAW spec fails to verify. At first glance, it does seem like this should work, since you are very careful to treat the Cryptol The reason this happens is because when SAW performs symbolic execution, it frequently attempts to concretize certain terms. This is often a huge win for performance, as evaluating concrete terms is much faster than evaluating symbolic ones. But there is a tension between concretization and uninterpreted functions: if you attempt to concretize things too much, you might accidentally evaluate something that was never meant to be evaluated, since as a Cryptol As such, SAW uses heuristics to figure out when to concretize terms or not, and these heuristics aren't perfect. In particular, whenever it sees a function application int x = 1;
*y = prim(x); After that gets translated to SAWCore, that looks something like:
Here, SAW sees a function applied to a concrete term This is all rather unfortunate, but there are ways to restructure things such that avoid driving the heuristics into overly eager concretization. One way is to make your int foo(int* y, int x){
*y = prim(x);
return 1;
} Note that
Then the verification succeeds, since when SAW sees the function application If changing the C code isn't an option, another way you can make this work is by changing
(Sorry for the exposition dump, but this stuff is rather subtle.) Returning to the topic of your PR, my understanding of your changes is that whenever SAW crashes when trying to concretize a SAWCore For this reason, I'm rather leery about this change, as I think this could have unforeseen consequences down the line. My inclination is to instead have users be more explicit about their intentions when using uninterpreted functions, by using |
Thanks for the detailed explanation! However, I don't think the proposed changes will satisfy my needs. Changing the C code that much is not an option like you predicted. If I understand correctly, the second option will not declare Your understanding of the PR is correct. How would you rather make the change to SAW so that it will solve the problem but won't have unpredictable consequences? I'm thinking maybe there should be a user interface that specifies certain function to be exceptions to concrete evaluation. Then inside concrete evaluation, it will not try to evaluate those function calls. What about this solution? |
Truth be told, I don't actually know off-hand which part of the symbolic execution engine is responsible for implementing the aforementioned heuristics, so it's difficult to say if it would be straightforward to do this. That being said, if you need something that works in today's SAW, then something like this ought to suffice:
Here, I've added an additional |
That's an interesting proposal. Let me try it out and get back to you! |
Hi @RyanGlScott, the last proposal works for us. I defined a function primitive.saw
Primitive.cry
Thank you so much for your help! |
Closing because issue is resolved with a workaround. |
Great, thank you for confirming. For what it's worth, I do think that SAW ought to be able to handle something like your original example, given that SAW's symbolic evaluator already has knowledge about what things should be left uninterpreted. I'll open a separate issue to track this. |
I've opened #1906 for this. |
Problem:
Say there is a user-declared
primitive
in Cryptol specification. Theprimitive
doesn't have a definition. During override matching phase, theprimitive
is being concretely evaluated because its arguments could be reduced to concrete values.Observation:
This causes SAW to fail and exit the REPL with the following error message:
What is done:
This PR fixes the problem by catching the error produced by concrete evaluation and gracefully return
Nothing
instead of causing SAW to fail. By doing this, the terms that could not be reduced to concrete values are treated as non-ground terms.