-
Notifications
You must be signed in to change notification settings - Fork 274
Memory snapshot harness havoc #4351
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
Memory snapshot harness havoc #4351
Conversation
Only the actual havoc-ing commit (for early feedback), documentation and tests are coming. |
3ee09ca
to
eeb1139
Compare
doc/cprover-manual/goto-harness.md
Outdated
function to work in arbitrary environment. If we want a more restricted | ||
environment or if we have the program in which our function will only be called, | ||
we call the `memory-snapshot` harness instead. |
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 call -> we can 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.
Done.
doc/cprover-manual/goto-harness.md
Outdated
### The memory snapshot harness | ||
|
||
The `function-call` harness is used in situations when we want the analysed |
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.
situations when -> situations in which
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.
Done.
doc/cprover-manual/goto-harness.md
Outdated
The `function-call` harness is used in situations when we want the analysed | ||
function to work in arbitrary environment. If we want a more restricted | ||
environment or if we have the program in which our function will only be called, |
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.
remove 'only' function will only be called
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 wanted "only" there somewhere. What about:
..or if we have the only program in which our function will be called..
?
doc/cprover-manual/goto-harness.md
Outdated
we call the `memory-snapshot` harness instead. | ||
|
||
Furthermore, the program state of interest may be taken a particular location |
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.
remove 'taken' ? might be clear enough. Alternatively - 'taken from'
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 about "taken at a particular location"?
doc/cprover-manual/goto-harness.md
Outdated
``` | ||
|
||
But are not particularly interested in the analysing the complex function, since |
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.
'interested in the' -> 'interested in analysing'
pps sorry about all the minor fixes. 100% aware english is not your 1st language - and you're doing great.
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.
Done. And no reason to apologise, the language is important especially in the manual.
175f325
to
3208756
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.
This looks good to me overall.
we trust that its implementation is correct. Hence we run the above program | ||
stopping after the assignments to `x` and `x` and storing the program state, | ||
e.g. using the `memory-analyzer`, in a JSON file `snapshot.json`. Then run the |
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 we have any documentation for the memory-analyzer
? I recall seeing some around, but I can't seem to be able to find it now? If we don't, would it be a good idea to write some separate documentation for that as well?
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.
7d6dc91
to
11c311b
Compare
11c311b
to
e207cfe
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.
✔️
Passed Diffblue compatibility checks (cbmc commit: aeff777).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/104250683
^SIGNAL=0$ | ||
\[main.assertion.1\] line [0-9]+ assertion x == 1: FAILURE | ||
-- | ||
^warning: ignoring |
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 it would be helpful to document how the JSON snapshots were generated. There will be a day where we need to change them in some way.
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.
That documentation was intended to be a part of #4261 (as we used the memory-analyzer to generate the JSON). Do you think it should be documented here as well?
if(variables_to_havoc.count(symbol.base_name) == 0) | ||
{ | ||
code_assignt code_assign(symbol.symbol_expr(), symbol.value); | ||
code.add(code_assign); |
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.
Nit picking: I don't think the code_assign
temporary adds value, you might just do code.add(code_assignt{...});
. If you do prefer to keep it I'd suggest to use code.add(std::move(code_assign));
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.
Done.
@@ -48,30 +49,92 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort | |||
{ | |||
} | |||
|
|||
/// 1. load memory table from the snapshot |
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'd start this documentation with a one-sentence summary. Otherwise I'd suspect this to render awkwardly.
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.
Done.
@@ -48,30 +49,92 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort | |||
{ | |||
} | |||
|
|||
/// 1. load memory table from the snapshot | |||
/// 2. add initial section to the initial location |
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.
Also I think it would be nice to make these proper sentences, starting with an uppercase letter and terminated with a full stop.
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.
Done.
void validate_options() override; | ||
|
||
/// Parse the snapshot JSON file and initialise the symbol table | ||
/// \param file: the snapshot JSON file | ||
/// \param snapshot: the resulting symbol table build from the snapshot |
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.
s/build/built/
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.
Done.
void | ||
get_memory_snapshot(const std::string &file, symbol_tablet &snapshot) const; | ||
|
||
/// Turn 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.
I'd start with a one-sentence summary. Otherwise this likely renders awkwardly.
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.
Done.
void add_init_section(goto_modelt &goto_model) const; | ||
|
||
/// For each global symbol in the \p snapshot symbol table either: | ||
/// 1) add \ref code_assignt assigning a value from the \p snapshot to the | ||
/// 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.
add "or"
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.
Done.
doc/cprover-manual/goto-harness.md
Outdated
The `function-call` harness is used in situations in which we want the analysed | ||
function to work in arbitrary environment. If we want a more restricted | ||
environment or if we have the program in which our function will be called, |
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.
or if we have an executable program in which
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.
Done.
doc/cprover-manual/goto-harness.md
Outdated
initial location does not have to be the first instruction of a function: we can | ||
also specify the _location number_ `n` to set the initial location inside our | ||
function. The _location numbers_ do not have to co-relate with the lines of the |
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.
s/co-relate/correlate/ (or maybe "coincide")
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.
Done.
aeff777
to
2240eb9
Compare
@@ -21,7 +21,8 @@ Author: Daniel Poetzl | |||
|
|||
#define MEMORY_SNAPSHOT_HARNESS_GENERATOR_OPTIONS \ | |||
"(memory-snapshot):" \ | |||
"(initial-location):" // MEMORY_SNAPSHOT_HARNESS_GENERATOR_OPTIONS | |||
"(initial-location):" \ | |||
"(havoc-variables):" // MEMORY_SNAPSHOT_HARNESS_GENERATOR_OPTIONS |
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 section should have // clang-format off
and // clang-format on
options to prevent clang-format from messing up the formatting here
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.
Done.
code_blockt &code) const | ||
{ | ||
recursive_initialization_configt recursive_initialization_config; | ||
auto recursive_initialization = util_make_unique<recursive_initializationt>( |
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 you're just using this in-place here there's no need for dynamic allocation... we only had that in the other harness generator because it was a stateful mess
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.
Done.
@@ -54,6 +56,10 @@ void memory_snapshot_harness_generatort::handle_option( | |||
location_number = optionalt<unsigned>(safe_string2unsigned(start.back())); | |||
} | |||
} | |||
else if (option == "havoc-variables") |
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.
s/variables/globals?
doc/cprover-manual/goto-harness.md
Outdated
### The memory snapshot harness | ||
|
||
The `function-call` harness is used in situations when we want the analysed |
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 find this sentence to be a bit awkward. The point of the snapshot harness is to analyse a function starting from a "real" program state (or a subset thereof)
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.
Changed.
doc/cprover-manual/goto-harness.md
Outdated
within a function. In that case we do not want the harness to instrument the | ||
whole function but rather to allow starting the execution from a specific | ||
initial location (specified via `--initial-location func[:<n>]`). |
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.
Might be worth noting here that the --initial-location
here should match the program location at the original breakpoint location
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.
Added.
|
||
int main() | ||
{ | ||
assert(x == 1); |
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 exactly is this test testing? Presumably this assertion would still fail if the snapshot harness didn't work?
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.
Modified.
fill_array(large_array, array_size); | ||
y = array_sum(large_array, array_size); | ||
checkpoint(); | ||
assert(y + 2 > x); |
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.
can you have an assert(false)
after checkpoint
just to check that the generated code actually makes this part still reachable?
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 looks reasonable, but I'd take another look at the regression tests
2240eb9
to
0074f5e
Compare
Basically just grabs a list of var-names from command line and calls recursive initialize on them instead of assigning their value.
Code level documentation for the class methods.
Covering memory-snapshot harness, but not the memory analyzer.
0074f5e
to
1425e3a
Compare
For global int, global struct, multiple snapshot-ed symbols, multiple havoc-ed symbols.
1425e3a
to
ceaafdf
Compare
This PR adds the option to selectively initialise global variables from a snapshot to a non-deterministic value rather than the value they had in the snapshot.
The scope of this PR are global variables of primitive types but since we use the
recursive_initialization
for the havoc-ing, the scope is inherited from the goto-harness general. At this moment,struct_tag
,pointer
, andarray
have dedicated treatment. On the other hand it is not within the scope of this PR to modify the configuration of the recursive initialization, i.e. the default values are used.