Skip to content

Commit 3ee09ca

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Cumulative commit
Will be squashed later.
1 parent f7ce86f commit 3ee09ca

File tree

4 files changed

+90
-2
lines changed

4 files changed

+90
-2
lines changed

doc/cprover-manual/goto-harness.md

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ having to manually construct an appropriate environment.
1313

1414
We have two types of harnesses we can generate for now:
1515

16-
* The `memory-snapshot` harness. TODO: Daniel can document this.
1716
* The `function-call` harness, which automatically synthesises an environment
1817
without having any information about the program state.
18+
* The `memory-snapshot` harness, which loads an existing program state (in form
19+
of a JSON file) and selectively _havoc-ing_ some variables.
1920

2021
It is used similarly to how `goto-instrument` is used by modifying an existing
2122
GOTO binary, as produced by `goto-cc`.
@@ -309,4 +310,57 @@ main.c function function
309310

310311
** 0 of 1 failed (1 iterations)
311312
VERIFICATION SUCCESSFUL
312-
```
313+
```
314+
315+
### The memory snapshot harness
316+
317+
The `function-call` harness is used in situations when we want the analysed
318+
function to work in arbitrary environment. If we want a more restricted
319+
environment or if we have the program in which our function will only be called,
320+
we call the `memory-snapshot` harness instead.
321+
322+
Furthermore, the program state of interest may be taken a particular location
323+
within a function. In that case we do not want the harness to instrument the
324+
whole function but rather to allow starting the execution from a specific
325+
initial location (specified via `--initial-location func[:<n>]`).
326+
327+
Say we want to check the assertion in the following code:
328+
329+
```C
330+
// main.c
331+
unsigned int x;
332+
unsigned int y;
333+
334+
unsigned int complex_function_which_returns_one() {
335+
unsinged int i = 0;
336+
while (i < 1000000000) {
337+
if (y)
338+
break;
339+
}
340+
return i & 2;
341+
}
342+
343+
int main() {
344+
x = complex_function_which_returns_one();
345+
assert(y + 2 > x);
346+
return 0;
347+
}
348+
```
349+
350+
But are not particularly interested in the analysing the complex function, since
351+
we trust that its implementation is correct. Hence we run the above program
352+
stopping after the assignment to `x` and storing the program state, e.g. using
353+
the `memory-analyzer`, in a JSON file `snapshot.json`. Then run the harness and
354+
verify the assertion with:
355+
356+
```
357+
$ goto-cc -o main.gb main.c
358+
$ goto-harness \
359+
--harness-function-name harness \
360+
--harness-type initialise-with-memory-snapshot \
361+
--memory-snapshot snapshot.json \
362+
--initial-location main:1 \
363+
--havoc-variables x \
364+
main.gb main-mod.gb
365+
$ cbmc --function harness main-mod.gb
366+
```
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int x;
2+
3+
int main()
4+
{
5+
assert(x == 1);
6+
7+
return 0;
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--harness-type initialise-with-memory-snapshot --memory-snapshot ../load-snapshot-json-snapshots/global-int-x-1-snapshot.json --initial-location main:0 --havoc-variables x
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
\[main.assertion.1\] line [0-9]+ assertion x == 1: FAILURE
7+
--
8+
^warning: ignoring

src/goto-harness/memory_snapshot_harness_generator.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,35 @@ class memory_snapshot_harness_generatort : public goto_harness_generatort
5353
override;
5454

5555
protected:
56+
/// Collect the memory-snapshot specific cmdline options (one at a time)
57+
/// \param option: memory-snapshot | initial-location | havoc-variables
58+
/// \param values: list of arguments related to a given option
5659
void handle_option(
5760
const std::string &option,
5861
const std::list<std::string> &values) override;
5962

63+
/// Check that user options make sense:
64+
/// On their own, e.g. location number cannot be specified without a function.
65+
/// In relation to the input program, e.g. function name must be known via
66+
/// the symbol table.
6067
void validate_options() override;
6168

69+
/// Parse the snapshot JSON file and initialise the symbol table
70+
/// \param file: the snapshot JSON file
71+
/// \param snapshot: the resulting symbol table build from the snapshot
6272
void
6373
get_memory_snapshot(const std::string &file, symbol_tablet &snapshot) const;
6474

6575
void add_init_section(goto_modelt &goto_model) const;
6676

77+
/// For each global symbol in the \p snapshot symbol table either:
78+
/// 1) add \ref code_assignt assigning a value from the \snapshot to the
79+
/// symbol
80+
/// 2) recursively initialise the symbol to a non-deterministic value of the
81+
/// right type
82+
/// \param snapshot: snapshot to load the symbols and their values from
83+
/// \param goto_model: model to initialise the havoc-ing
84+
/// \param code: block of code where the assignments are added
6785
void add_assignments_to_globals(
6886
const symbol_tablet &snapshot,
6987
goto_modelt &goto_model,

0 commit comments

Comments
 (0)