-
Notifications
You must be signed in to change notification settings - Fork 269
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
introduce 'fatal assertions' #8226
Conversation
fa9256f
to
8f8e599
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #8226 +/- ##
===========================================
+ Coverage 77.96% 78.37% +0.40%
===========================================
Files 1720 1721 +1
Lines 188982 188083 -899
Branches 18391 18452 +61
===========================================
+ Hits 147347 147404 +57
+ Misses 41635 40679 -956 ☔ View full report in Codecov by Sentry. |
8f8e599
to
f24b721
Compare
58bdc8c
to
2a08484
Compare
Is UNKNOWN the right status here? Or should there are rather be a new status UNDEFINED? |
I did think about revising the status outputs to increase clarity. But that should happen independently, as a separate discussion. An issue with "UNDEFINED" is that the word "undefined behavior" is very specific to C/C++, and we may wish our status codes to be more general. Also, it may mislead a reader to believe that there is undefined behavior at the given location. There may well be, but the point is that the undefined behavior is before that assertion in program order. |
In Kani, we use UNDETERMINED. |
I've pulled out the question of division-by-zero for floating-point numbers into a separate PR: #8233 |
2a08484
to
a393868
Compare
a393868
to
66e5329
Compare
Are fatal assertions encoded as assert + assume? How customizable will this new assertion be? Will users also be able to instrument their code with fatal assertions? |
I am afraid that would yield the opposite result: you'd be more likely to get SUCCESS for the downstream properties, making the user believe that they are proven when really they are not.
We could certainly consider a |
In Kani, we over-approximate by marking all passing properties as undetermined. |
66e5329
to
e9622b3
Compare
With a new option --assert-then-assume each built-in check (assertion) is followed by an assumption. For Kani, this will enable more consistent behaviour, and it may give us an additional way to produce "fatal assertions" as proposed in diffblue#8226.
#8242 now implements the assert + assume when users request this. |
c1c781b
to
c8c61ca
Compare
This now marks refuted assertions after refuted fatal assertions as UNKNOWN. |
4d88965
to
f6e0d9f
Compare
This comes at a price: to identify those assertions, the trace needs to be computed. That trace computation is broken in a number of cases, now marked as KNOWNBUG. Note that these aren't regressions caused by this PR, but just exposed by this PR. We can try to fix these beforehand, and delay this PR. I believe that the step towards reporting sound results is very important, and that we should do it for 6.0. |
What kind of brokenness is this? I have previously only seen that computing traces can be very expensive (see #5714). |
It seems to be a miscellaneous set of issues that get triggered by calling I didn't see a case of things getting very slow, but I'd say that's just as bad as throwing an error. This ought to be linear. |
5cc78c4
to
0ad525c
Compare
be78e8c
to
eb9ccc9
Compare
@@ -7,4 +7,3 @@ user.json_symtab library.json_symtab | |||
^\[2\] file library.adb line \d+ assertion: FAILURE$ | |||
^VERIFICATION FAILED$ | |||
-- | |||
error |
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.
Why did this line get removed?
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.
The test triggered on "error trace", i.e., fails when --trace
is added.
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.
But ... this PR no longer adds a need to compute traces?
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.
Yes, but our future selves still want this. But could pull over into separate 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.
I'm sorry, I had to convince myself of the problem... Done and now PR'ed as #8270.
@@ -7,4 +7,3 @@ entry_point.json_symtab | |||
^\[2\] file entry_point.adb line \d+ assertion: SUCCESS$ | |||
^VERIFICATION FAILED$ | |||
-- | |||
error |
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.
Same here: Why did this line get removed?
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.
Maybe add tests with mutually recursive functions containing fatal assertions
if(!insertion_result.second) | ||
continue; // seen already | ||
|
||
if(loc.target->is_function_call()) |
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.
does this assume that function pointer calls have been eliminated ?
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.
Yes.
|
||
/// Proven assertions after refuted fatal assertions | ||
/// are marked as UNKNOWN. | ||
void propagate_fatal_to_proven( |
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.
why keep refuted assertions after refuted fatal assertions intact ? The counter example could also be spurious or not worth investigating.
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.
Note the discussion on the PR. The problem is that enabling the computation of counterexamples is expensive and doesn't work. Hence I've taken that out again.
{ | ||
// Iterate to find refuted fatal assertions. Anything reachalble | ||
// from there is a 'fatal loc'. | ||
loc_sett fatal_locs; |
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 there a risk to flip the status of a fatal assertion from FAIL to UNKOWN if the goto model contains mutually recursive functions ? (a fatal assertion could appear to be after itself ?)
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, assertions that are failed simply stay 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.
Is there a documentation update for fatal assertions ?
Are there ways to invoke CBMC which would result in the propagation not happening ?
i.e. is all_properties_verifier_with_trace_storaget
the only verifier that users can invoke through the CLI ?
This is a bigger job. It will need to be done eventually, but I'd do it as part of a bigger doc overhaul. It requires explaining what UB is, why it's bad, and why it's not locally contained.
Not that I know of. |
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.
Approving, but would appreciate if #8270 could be merged first to have a proper separation of concerns.
This introduces a variant of ASSERT instructions that are fatal when they are refuted. Execution paths through fatal assertions that are refuted are undefined. Assertions that (otherwise) pass and that are reachable from a refuted fatal assertion are now reported as UNKNOWN. The motivating use-case for fatal assertions is undefined behavior in languages such as C/C++ or Rust. Noi attempt is made to modify the outcome of ASSERT instructions that are refuted owing to a trace through a refuted fatal assertion. The computation of the trace is not robust enough.
eb9ccc9
to
3cdd832
Compare
This introduces a variant of
ASSERT
instructions that are fatal when they are refuted. Execution paths through fatal assertions that are refuted are undefined. Assertions that (otherwise) pass and that are reachable from a refuted fatal assertion are now reported asUNKNOWN
.The motivating use-case for fatal assertions is undefined behavior in languages such as C/C++ or Rust.