-
Notifications
You must be signed in to change notification settings - Fork 273
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
Enable default analysis flags for CBMC version 6.0+ #8093
Enable default analysis flags for CBMC version 6.0+ #8093
Conversation
src/ansi-c/goto_check_c.h
Outdated
"(assert-to-assume)" | ||
"(assert-to-assume)" \ | ||
"(no-bounds-check)(no-pointer-check)(no-signed-overflow-check)" \ | ||
"(no-pointer-primitive-check)(no-undefined-shift-check)" |
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.
Missing "no-div-by-zero-check
?
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.
Yeah, this was missed. I've added it now.
src/cbmc/cbmc_parse_options.cpp
Outdated
options.set_option("bounds-check", true); | ||
options.set_option("pointer-check", true); | ||
options.set_option("pointer-primitive-check", true); | ||
options.set_option("div-by-zero-check", true); | ||
options.set_option("signed-overflow-check", true); | ||
options.set_option("undefined-shift-check", true); |
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.
Aren't all of these then re-set later depending on the [no-]standard-checks
option?
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 code is called depending on whether the no-standard-checks
is set.
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.
Aren't they called on both line 140 and line 337?
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.
Ah, I see what you mean now. Yeah, that has been eliminated now :) Good catch, it was an artefact of a previous design that set the default options unconditionally, and then if the --no-standard-checks
flag was present it was just overriding it.
Now we've moved to a design that sets or doesn't set based on the flag being present.
src/cbmc/cbmc_parse_options.cpp
Outdated
|
||
// Unwinding assertions required in certain cases for sound verification | ||
// results. See https://github.com/diffblue/cbmc/issues/6561 for elaboration. | ||
options.set_option("unwinding-assertions", true); |
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.
Line 144 below now needs to handle this being set on be default. Maybe also line 287?
43ebc37
to
2d7a5ee
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.
The handling of the malloc
checks looks wrong. This is the main blocking comment which needs to be addressed.
My overarching remaining nitpick is that perhaps everything carried out by your duplicated set_default_analysis_flags
functions should actually be done elsewhere. If you move all the functionality out of the functions, they will be unneeded and then duplication can be resolved by removing them.
@@ -56,6 +56,25 @@ goto_analyzer_parse_optionst::goto_analyzer_parse_optionst( | |||
{ | |||
} | |||
|
|||
void goto_analyzer_parse_optionst::set_default_analysis_flags(optionst &options) | |||
{ | |||
// Checks enabled by default in v6.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.
The code in goto_analyzer_parse_optionst::set_default_analysis_flags
and cbmc_parse_optionst::set_default_analysis_flags
is duplicated. This is is a potential maintenance issue, to keep them synchronised.
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 stay as it is, because these two functions may be equivalent in form, but they represent different knowledge - the default configuration of two tools that are functionally different (one is a model checker and the other is an abstract interpreter), which only incidentally happens to be similar now, and could very well develop independently in the future.
options.set_option("pointer-primitive-check", true); | ||
options.set_option("div-by-zero-check", true); | ||
options.set_option("signed-overflow-check", true); | ||
options.set_option("undefined-shift-check", true); |
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 per @TGWDB comment, the options in the PARSE_OPTIONS_GOTO_CHECK_NEGATIVE_DEFAULT_CHECKS
macro don't need to be in this function. This is because the macro sets the options after this function is called and it will set the value of the option regardless of whether it needs to be true or 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.
The PARSE_OPTIONS_GOTO_CHECK_NEGATIVE_DEFAULT_CHECKS
's main functional aim is to be there to overwrite the flags in case they happen to be different (say, if a user is using default checks, but also --no-div-by-zero-check
).
I agree that the end result is setting the flags to true
twice, but I like that they are present in set_default_analysis_flags
as documentation of the tool's default behaviour at the very least, and also without having to depend on flags being implicitly set to the default values by inverted logic in a different place in the code (goto_check_c.h
).
src/cbmc/cbmc_parse_options.cpp
Outdated
|
||
// Default malloc failure profile chosen to be returning null. | ||
options.set_option("malloc-may-fail", true); | ||
options.set_option("malloc-fail-null", true); |
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 doesn't look right. In develop
the malloc-may-fail
argument and the malloc-fail-null
argument are never added to (or read from) the options. Therefore it appears to me that adding them to the options will have no effect. The command line arguments are read from cmdline
and immediately used to setup configt::ansi_ct
. See
Line 1124 in 64fe4d0
if(cmdline.isset("malloc-fail-null")) |
It might be worth considering implementing the default in the above location, in order to keep all the logic for the malloc checks in the same 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.
Thank you for the catch!
I have attempted a fix in 71cda7c that I think should achieve the same end-goal but keep the code a bit cleaner. It achieves that by restricting the knowledge about the standard checks inside the cbmc_parse_optionst
and goto_analyzer_parse_optionst
. I think that changing the config.set
function would distribute the knowledge about default flags (which for now is strictly a CBMC/goto-analyzer thing) into multiple places, making it harder to follow, and making the configuration (for other tools, as config.set
is invoked in 30+ places) more convoluted without any direct correspondence to actual flags.
src/cbmc/cbmc_parse_options.cpp
Outdated
|
||
// Unwinding assertions required in certain cases for sound verification | ||
// results. See https://github.com/diffblue/cbmc/issues/6561 for elaboration. | ||
options.set_option("unwinding-assertions", true); |
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 goto_instrument
can be used to perform unwinding, shouldn't this new default be applied in that entry point in that case?
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.
Hm, I think in that case it probably wouldn't matter, because the analysis tools (the two main ones - cbmc
and goto-analyzer
) would add these, if I understand this correctly.
I need to play with this a bit and get back to you.
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 unwinding is a transformation, rather than an analysis on its own right, I think this option needs to be set correctly for which ever entry point is performing the the transformation. My current assumption is that the unwinding assertions are added during the unwinding process. So the usual process flow is that the unwinding and the assertions would be done as part of the cbmc entry point. But if unwinding is performed on the goto-program before cbmc
then the analysis won't go back and add the assertions which should have been added prior.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #8093 +/- ##
========================================
Coverage 79.08% 79.09%
========================================
Files 1698 1698
Lines 196457 196485 +28
========================================
+ Hits 155370 155401 +31
+ Misses 41087 41084 -3 ☔ View full report in Codecov by Sentry. |
@@ -59,4 +59,4 @@ elif echo $args_inst | grep -q -- "--dump-c" ; then | |||
rm "${name}${dfcc_suffix}-mod.c" | |||
fi | |||
$goto_instrument --show-goto-functions "${name}${dfcc_suffix}-mod.gb" | |||
$cbmc "${name}${dfcc_suffix}-mod.gb" ${args_cbmc} | |||
$cbmc --no-standard-checks "${name}${dfcc_suffix}-mod.gb" ${args_cbmc} |
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.
Please don't do this. It will be very though for anyone to work out what the tests actually do execute when one fails.
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 @kroening, just for clarification:
We were hoping to use this approach as a stop-gap to allow us to get the regression test suite in a way that is all-green again, so that we could merge this in time, seeing as this is the main ticket that's blocking a v6 release.
But the aim was to get this in temporarily, and as soon our v6 release is unblocked, reopen #8006, rebase it and then move to a model where the extra flag is being passed on an individual basis to tests (to localise the information about the test on the individual .desc
file).
The original approach (of getting all the .desc
readjusted) was found to be time consuming, and we wanted to at least unblock the release before we embark on that.
Is that something that works for you? If not, is there a particular proposal you had mind?
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's ok to use --no-standard-checks
on most of the tests; my suggestion is to add it to the .desc
file, where everyone will see it, instead of burying it inside a script.
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 agree that the place for the --no-standard-checks
flag is the .desc
file of each failing test.
Unfortunately there are about 300
failing tests, so the idea was to avoid having a PR with code changes in the middle of 300
repetitive test fixes, but instead to temporarily add --no-standard-checks
to the scripts to pass CI and them fix all the failing test on a subsequent PR aimed solely at fixing the regression tests.
@kroening I hope that this clarifies why the --no-standard-checks
flag has been added on the runner script at the moment.
💡 Since we have now combinations of flags that turn on and off checks, it would be great to output the list of actually active checks to the console. |
5992227
to
cac6ead
Compare
cac6ead
to
4fdab91
Compare
5ff9d49
to
ea83bc9
Compare
So that the defaults can be selectively overridden, whether they are initially on or off.
This allows for parsing the whole set of options regardless of whether the default is true or false. This then simplifies the usage of the macro as the separate option parsing no longer depends on if "no-standard-checks" is specified.
The `optionst` class essentially uses tri-state logic for booleans, where an option may be true, false or unset. `is_set` will return `true` for both the true and false options. Therefore we need `get_bool_option` to get the state of whether the option is set to true or false.
As the default is now to switch on the unwinding-assertions, we don't want a user to have to specify `--no-unwinding-assertions` in order to use `--cover`.
It will be handled in next PR.
ea83bc9
to
9747f61
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 am approving as the malloc changes have been removed, for handling this separately.
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 to unblock the pre-release, given the promise that open requests come in a separate PR.
With additional checks turned on as of diffblue#8093, we failed CSmith tests with (legitimate) pointer property failures in `strcmp`. These are caused by trying to compare `argv[1]` to a string. As we do not model `argv` in these tests, `argv[1]` was not a valid pointer. This fix just removes the string comparison, which is only used for turning on/off debug output in test execution.
This is a cleaned up version of #8006.
There are two difference over the previous PR:
--no-standard-checks
flag in all of the regression test runners, instead of adjusting flags on each failing test. The reason we need to adjust flags to begin with is that a lot of tests are checking for number of properties or specific labels in the output, which, now that we enable a lot more properties by default, have been invalidated.cbmc_parse_options
andgoto_check_c
. Previous version rejected a flag that was on by default, such as--pointer-check
, this version silently ignores it.Still to-do:
goto-analyzer
as well.