-
Notifications
You must be signed in to change notification settings - Fork 274
Invariant cleanup in goto programs i* #2952
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
Invariant cleanup in goto programs i* #2952
Conversation
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.
Passed Diffblue compatibility checks (cbmc commit: 6ff3096).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/84818543
if(v.size()!=1) | ||
throw "invalid boolean value"; | ||
throw interpreter_errort("invalid boolean value"); |
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 wonder if this shouldn't be an invariant. The input expr
is always the path condition of the interpreted program and I don't think the user is directly responsible for what the interpreter chooses to be a path condition.
129444d
to
cd0bd66
Compare
cd0bd66
to
dec77b7
Compare
dec77b7
to
79efa6d
Compare
79efa6d
to
11af196
Compare
msg.error() << "failed to figure out type of file" << messaget::eom; | ||
throw 0; | ||
throw invalid_source_file_exceptiont( | ||
"Failed to figure out type of file `" + filename + '\''); |
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.
This should arguably happen before the check whether the file can be opened, but that's a minor point and not really within the spirit of this PR
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.
This PR failed Diffblue compatibility checks (cbmc commit: 79efa6d).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87615645
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.
Common spurious failures:
- the cbmc commit has disappeared in the mean time (e.g. in a force-push)
- the author is not in the list of contributors (e.g. first-time contributors).
The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.
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.
It might be a little bit more readable if the variable renaming was in a separate commit. But other than that, it looks good to me.
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.
Thanks for the clean-up. Comments are mostly opinions on what kind of error conditions these are.
@@ -69,12 +69,12 @@ void interpretert::initialize(bool init) | |||
main_it=goto_functions.function_map.find(goto_functionst::entry_point()); | |||
|
|||
if(main_it==goto_functions.function_map.end()) | |||
throw "main not found"; | |||
throw analysis_exceptiont("main not found"); |
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.
Is this actually a structural invariant on goto-programs?
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 wasn't sure about this one, because you might have goto programs without an entry point (libraries mostly). I suppose it could be a precondition if we assume that a caller should've checked for an entry point before calling this.
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.
It is getting in to the heart of why we need to check that goto-programs are well formed and to clarify what "normal forms" exist for them. If it has been linked and is a complete goto program then it should have an entry point which is a function in the map. If it is only partially built (goto-cc -c for example) then it may not do. It is not immediately clear to me whose fault it would be to try to interpret a n "object file" rather than an "executable".
|
||
const goto_functionst::goto_functiont &goto_function=main_it->second; | ||
|
||
if(!goto_function.body_available()) | ||
throw "main has no body"; | ||
throw analysis_exceptiont("main has no body"); |
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.
As above.
throw "RETURN without call"; // NOLINT(readability/throw) | ||
{ | ||
throw analysis_exceptiont( | ||
"RETURN without call"); // NOLINT(readability/throw) |
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 this is an INVARIANT as if the interpreter is working as it should, then this should never happen.
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 was thinking this could happen in a nonsensical goto program that has returns in unexpected places, such as __CPROVER_initialize
. Is that wrong?
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.
If I understand the code correctly (and it is possible I don't) then the INVARIANT is that the number of RETURNS executed should never exceed the number of functions started. So this should always hold.
@@ -317,19 +320,23 @@ void interpretert::step() | |||
|
|||
case START_THREAD: | |||
trace_step.type=goto_trace_stept::typet::SPAWN; | |||
throw "START_THREAD not yet implemented"; // NOLINT(readability/throw) | |||
throw analysis_exceptiont( | |||
"START_THREAD not yet implemented"); // NOLINT(readability/throw) |
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.
UNIMPLEMENTED ? Also below.
@@ -359,7 +366,7 @@ void interpretert::step() | |||
case CATCH: | |||
break; | |||
default: | |||
throw "encountered instruction with undefined instruction type"; | |||
UNREACHABLE; // I'm assuming we'd catch such a thing before this point |
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.
Sounds like you're saying it is a consequence of the goto program being well-formed ;-)
@@ -724,15 +730,15 @@ void interpretert::assign( | |||
void interpretert::execute_assume() | |||
{ | |||
if(!evaluate_boolean(pc->guard)) | |||
throw "assumption failed"; | |||
throw analysis_exceptiont("assumption failed"); |
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.
Unrelated to this; I'm not sure this is the right way of handling this case. I think it should just terminate correctly.
This mostly entails using to_XXX_expr in place of using ad hoc asserts. At the same time, some minor cleanup work is done to improve the readability of the affected code
11af196
to
ce7f792
Compare
@martin-cs Yes, since I'm not super familiar with this code myself I was a bit unclear in many cases about whether INVARIANT or exception is the better 'mechanism' to use. I'll have another look over the cases you pointed out. |
@hannes-steffenhagen-diffblue : The test I tend to you is : if there are a set of user controllable flags and a non-corrupted / incorrect program that can cause it to happen, it is a potential user error and should be an exception. If the only way it can happen is if there are one or more bugs in CPROVER, then it should be an invariant of some kind. |
@martin-cs I completely agree with that, it's just difficult to judge on a case by case basis sometimes. |
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.
This PR failed Diffblue compatibility checks (cbmc commit: 11af196).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87644100
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.
Common spurious failures:
- the cbmc commit has disappeared in the mean time (e.g. in a force-push)
- the author is not in the list of contributors (e.g. first-time contributors).
The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.
Heads up, I'm a bit uncomfortable with putting these changes in as the interpreter seems to be broken and untested atm. See #3146 I'll extract the initialize_goto_model stuff as that seems to be unrelated |
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.
Passed Diffblue compatibility checks (cbmc commit: ce7f792).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/87649507
@hannes-steffenhagen-diffblue : It is difficult to judge; this is why I try to phrase my comments on these as "IMHO it should be". As regards the interpreter; it didn't use to be in a great state but I thought someone at Diffblue had taken over it's care and feeding. I have a vague feeling that @dcattaruzza was asking about it at one point... |
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 ok to me (with one comment below); but really this should be checked against TG, where I believe some interpreter tests exist.
if(v.size()!=1) | ||
throw "invalid boolean value"; | ||
throw analysis_exceptiont("invalid boolean value"); |
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 would drop the FIXME and turn this into an INVARIANT
. People will start complaining if it's not actually an invariant... :-)
I extracted the |
This PR is part of the invariant cleanup work, for the files in goto-programs starting with i.
This entails replacing asserts with cprover style invariants, using structured exception types and using
to_XXX_expr
style conversions instead of 'structure' asserts for expressions.