-
Notifications
You must be signed in to change notification settings - Fork 274
Disable unnecessary pointer checks, enable necessary pointer checks i… #6459
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
Disable unnecessary pointer checks, enable necessary pointer checks i… #6459
Conversation
bf54161
to
7c37804
Compare
@@ -116,6 +116,8 @@ const symbolt &new_tmp_symbol( | |||
const typet &type, | |||
const source_locationt &location, | |||
const irep_idt &mode, | |||
symbol_table_baset &symtab); | |||
symbol_table_baset &symtab, | |||
std::string suffix = "tmp_cc"); |
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 new parameter needs a doxygen comment above
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.
fixed
Codecov Report
@@ Coverage Diff @@
## develop #6459 +/- ##
========================================
Coverage 76.07% 76.08%
========================================
Files 1548 1548
Lines 166362 166387 +25
========================================
+ Hits 126567 126591 +24
- Misses 39795 39796 +1
Continue to review full report at Codecov.
|
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.
Generally ok with this, but the last commit introduces/modifies various tests and it is not obvious which tests are just additional tests, or which code changes these tests relate to.
return get_fresh_aux_symbol( | ||
type, | ||
id2string(location.get_function()) + "::tmp_cc", | ||
"tmp_cc", | ||
id2string(location.get_function()) + "::", | ||
suffix, | ||
location, | ||
mode, | ||
symtab); |
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.
While at it: should this code also be modified to have those symbols show up in counterexample traces? I found myself having a hard time understanding counterexamples for none of the assignments to these variables show up, but failing assertions then refer to them. The change required to facilitate this:
symbolt &new_symbol = get_fresh_aux_symbol(...);
new_symbol.is_auxiliary = false;
return new_symbol;
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.
Adding a new function argument 'is_auxiliary' to control that symbol per symbol.
@@ -52,14 +52,16 @@ static const slicet normalize_to_slice(const exprt &expr, const namespacet &ns) | |||
} | |||
|
|||
const symbolt assigns_clauset::conditional_address_ranget::generate_new_symbol( | |||
const std::string &prefix, |
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.
Random place for comment, and primarily for future reference: I would like to see commits like this be a pull request of their own. Changing the names of CAR instrumentation variables really has nothing to do with disabling selected checks.
source_locationt &location_no_checks = | ||
instruction_it->source_location_nonconst(); |
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.
Do you really want or need to take a reference here? The reference will ensure (but is that desired?) that checks are disabled on the function call. Otherwise, I would have expected that you'd be taking a copy here, at which point you want to use source_location()
instead of source_location_nonconst()
.
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.
fixed
@@ -1175,6 +1175,10 @@ void code_contractst::check_frame_conditions( | |||
else if(instruction_it->is_dead()) | |||
{ | |||
const auto &symbol = instruction_it->dead_symbol(); | |||
source_locationt &location_no_checks = | |||
instruction_it->source_location_nonconst(); | |||
disable_pointer_checks(location_no_checks); |
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: is the reference intentional?
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.
fixed
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.
We could add a comment here again explaining "why" is safe to always remove pointer checks in this location.
assigns.generate_inclusion_check(car), instruction_it->source_location())); | ||
assertion.instructions.back().source_location_nonconst().set_comment( | ||
source_locationt location_no_checks = | ||
instruction_it->source_location_nonconst(); |
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.
Certainly source_location()
instead of source_location_nonconst()
.
@@ -40,4 +42,4 @@ We also check (using positive regex matches above) that | |||
`**p` should be assignable in one case and should not be assignable in the other. | |||
|
|||
Finally, we check that there should be no "internal" assertion failures | |||
on `tmp_cc` variables used to track CARs. | |||
on `__car_valid`, `__car_ub`, `__car_lb` variables used to track CARs. |
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.
Changes in this file should be folded into the commit introducing the new names.
@@ -0,0 +1 @@ | |||
Reading GOTO program from '__CPROVER_file_local_s2n_hash_c_s2n_evp_hash_reset_with_contracts_harness.c.goto' |
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 is the meaning of this file?
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 is a debugging session leftover, removing it
7c37804
to
0b7535c
Compare
All review comments were addressed |
0b7535c
to
3aee2f7
Compare
…ter overflow checks on CAR upper bound computation.
3aee2f7
to
e2f4fec
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.
I was a bit too late to the party, but I'll leave the comments here to be addressed on another PR.
^.*__car_valid.*: FAILURE$ | ||
^.*__car_lb.*: FAILURE$ | ||
^.*__car_ub.*: FAILURE$ |
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.
nitpick: I'd prefer even more readable names for users: __car_valid
, __car_lower_bound
, and __car_upper_bound
. However, the fact that these variables exist should be transparent to users. Why would this variables appear as failures? I guess you want to make sure here there are no memory safety errors in any operation using these variables, is that correct?
const std::string &prefix, | ||
const typet &, | ||
const source_locationt &) const; |
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.
For consistency, add the name of the remaining parameters or remove prefix
.
symbol_table_baset &symtab, | ||
std::string suffix, |
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.
symbol_table_baset &symtab, | |
std::string suffix, | |
symbol_table_baset &symtab, | |
std::string &suffix, |
/// \param suffix: Suffix to use to generate the unique name | ||
/// \param is_auxiliary: Do not print symbol in traces if true (default = false) |
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.
/// \param suffix: Suffix to use to generate the unique name | |
/// \param is_auxiliary: Do not print symbol in traces if true (default = false) | |
/// \param suffix: Suffix to use to generate the unique name. | |
/// \param is_auxiliary: Do not print symbol in traces if true (default = false). |
// adding pragmas to the location to selectively disable checks | ||
// where it is sound to do so |
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 a brief explanation of "why" is sound to disable checks here would be more helpful, since one can easily infer this comment from the code.
|
||
// the computation of the CAR upper bound can overflow into the object ID bits | ||
// of the pointer with very large allocation sizes. | ||
// We enable pointer overflow checks to detect such cases. |
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.
// We enable pointer overflow checks to detect such cases. | |
// We always enable pointer overflow checks to detect such cases. |
// remark: both lb and ub are derived from the same object so checking | ||
// same_object(upper_bound_address_var, lhs.upper_bound_address_var) | ||
// is redundant |
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.
Nice!
// remark: both lb and ub are derived from the same object so checking | |
// same_object(upper_bound_address_var, lhs.upper_bound_address_var) | |
// is redundant | |
// Both lb and ub are derived from the same object so checking | |
// same_object(upper_bound_address_var, lhs.upper_bound_address_var) | |
// is redundant |
@@ -911,6 +911,8 @@ void code_contractst::instrument_call_statement( | |||
} | |||
else if(callee_name == "free") | |||
{ | |||
source_locationt location_no_checks = instruction_it->source_location(); | |||
disable_pointer_checks(location_no_checks); |
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.
We could add a comment here again explaining "why" is safe to always remove pointer checks in this location.
@@ -1175,6 +1175,10 @@ void code_contractst::check_frame_conditions( | |||
else if(instruction_it->is_dead()) | |||
{ | |||
const auto &symbol = instruction_it->dead_symbol(); | |||
source_locationt &location_no_checks = | |||
instruction_it->source_location_nonconst(); | |||
disable_pointer_checks(location_no_checks); |
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.
We could add a comment here again explaining "why" is safe to always remove pointer checks in this location.
assertion.instructions.back().source_location_nonconst().set_comment( | ||
source_locationt location_no_checks = | ||
instruction_it->source_location_nonconst(); | ||
disable_pointer_checks(location_no_checks); |
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.
We could add a comment here again explaining "why" is safe to always remove pointer checks in this location.
This PR fixes some performance issues with assigns clause checking for function and loop contracts.
The problem was that the goto variables and instructions generated to instrument the checks were themselves re-instrumented with automatic VCCs in subsequent passes, causing an explosion in the number of VCCs (with unwanted VCCs representing up to 85% of the total VCCs in some problems).
Instructions performing CAR inclusion checks are read-only logical expressions whose evaluation cannot fail so we can safely disable automatic checks on them.
CAR snapshotting instructions however perform some pointer arithmetic and need to be ultimately checked for pointer overflow.
In this PR:
The disable pragmas guard against reinstrumentation in later passes, and the enable pragmas make sure necessary checks will eventually be instantiated before analysis.