Skip to content

Commit a82c7d0

Browse files
authored
Merge pull request #5428 from NlightNFotis/goto_harness_docs_change
Changes to goto-harness documentation
2 parents febb5cf + 8b31985 commit a82c7d0

File tree

1 file changed

+92
-36
lines changed

1 file changed

+92
-36
lines changed

doc/architectural/goto-harness.md

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,29 @@
11
[CPROVER Manual TOC](../../)
22

3-
## Goto Harness
3+
# Goto Harness
44

5-
This is a tool that can generate harnesses, that is functions that instrument
5+
This is a tool for generating harnesses, that is, functions that instrument
66
another function under analysis, by setting up an appropriate environment before
77
calling them.
88

99
This is useful when trying to analyse an isolated unit of a program without
1010
having to manually construct an appropriate environment.
1111

12-
### Usage
12+
## Quick Start Guide
13+
14+
For a given C program - `program.c` - to generate a harness for a function
15+
`test_function`, we have to do the following:
16+
17+
```sh
18+
# Compile the program
19+
$ goto-cc program.c -o program.gb
20+
# Run goto-harness to produce harness file
21+
$ goto-harness --harness-type call-function --harness-function-name generated_harness_test_function --function test_function program.gb harness.c
22+
# Run the checks targetting the generated harness
23+
$ cbmc --pointer-check harness.c --function generated_harness_test_function
24+
```
25+
26+
## Detailed Usage
1327

1428
We have two types of harnesses we can generate for now:
1529

@@ -18,6 +32,9 @@ without having any information about the program state.
1832
* The `memory-snapshot` harness, which loads an existing program state (in form
1933
of a JSON file) and selectively _havoc-ing_ some variables.
2034

35+
**NOTE**: Due to a [bug](https://github.com/diffblue/cbmc/issues/5351), the
36+
`memory-snapshot` harness is currently inoperable. We are working to fix this.
37+
2138
It is used similarly to how `goto-instrument` is used by modifying an existing
2239
GOTO binary, as produced by `goto-cc`.
2340

@@ -45,15 +62,15 @@ $ goto-cc -o main.gb main.c
4562
```
4663

4764
Then we can call `goto-harness` on the generated GOTO binary
48-
to get a modified one that contains the harness function:
65+
to get a new C file that contains the harness function:
4966

5067
```sh
5168
$ goto-harness \
5269
--harness-function-name harness \
5370
--harness-type call-function \
5471
--function function_to_test \
5572
main.gb \
56-
main-with-harness.gb
73+
harness.c
5774
```
5875

5976
The options we pass to `goto-harness` are:
@@ -63,34 +80,66 @@ The options we pass to `goto-harness` are:
6380
* `harness-type` is the type of harness to generate (`call-function` is the
6481
function-call harness generator)
6582
* `function` is the name of the function that gets instrumented
66-
* then we pass the input GOTO-binary and a name for the output GOTO binary.
83+
* then we pass the input GOTO-binary and a name for the output C file.
6784

68-
What comes of this is a GOTO binary roughly corresponding to the following C
69-
pseudocode:
85+
What comes out of this is a C file that looks like this:
7086

7187
```C
72-
// modified_goto_binary.c
73-
74-
#include <assert.h>
75-
76-
int function_to_test(int some_argument)
88+
// function_to_test
89+
// file main.c line 3
90+
signed int function_to_test(signed int some_argument);
91+
// harness
92+
//
93+
void harness(void);
94+
// type_constructor_int
95+
//
96+
void type_constructor_int(signed int depth_int, signed int *result_int);
97+
98+
// __GOTO_HARNESS::max_depth
99+
// file __GOTO_HARNESSharness.c
100+
signed int max_depth=2;
101+
// __GOTO_HARNESS::min_depth
102+
// file __GOTO_HARNESSharness.c
103+
signed int min_depth=1;
104+
105+
// harness
106+
//
107+
void harness(void)
77108
{
78-
assert(some_argument == 0);
79-
return some_argument;
109+
signed int some_argument;
110+
type_constructor_int(0, &some_argument);
111+
function_to_test(some_argument);
80112
}
81113

82-
void harness(void)
114+
// type_constructor_int
115+
//
116+
void type_constructor_int(signed int depth_int, signed int *result_int)
83117
{
84-
int argument = nondet_int();
85-
function_to_test(argument);
118+
signed int nondet;
119+
*result_int = nondet;
86120
}
87121
```
88122
89-
You can pass that modified GOTO binary to `cbmc` and select `harness` as the
90-
entry function for analysis, or further modify it with `goto-harness` or
91-
`goto-instrument` or other tools.
123+
After you have generated the harness file, you have two choices. The first
124+
one is to pass it along with the original file containing the function to
125+
be harnessed to CBMC for analysis, something that would look like this:
126+
127+
```sh
128+
$ cbmc --function harness harness.c main.c
129+
[...]
130+
131+
[function_to_test.assertion.1] line 5 assertion some_argument == 0: FAILURE
132+
133+
** 1 of 1 failed (2 iterations)
134+
VERIFICATION FAILED
135+
```
136+
137+
Or, you could choose to turn it into another goto binary with `goto-cc`, to
138+
be served as input to another instrumentation tool (like `goto-instrument`).
92139

93-
The example above demonstrates the most simple case, which is roughly the same
140+
---
141+
142+
The example above demonstrates the simplest case, which is roughly the same
94143
as the entry point `cbmc` automatically generates for functions. However, the
95144
`function-call` harness can also non-deterministically initialise global
96145
variables, array and struct elements. Consider this more complicated example:
@@ -167,15 +216,15 @@ $ goto-harness \
167216
--min-null-tree-depth 1 \
168217
--nondet-globals \
169218
list_example.gb \
170-
list_example_with_harness.gb
171-
$ cbmc --function harness list_example_with_harness.gb --unwind 20 --unwinding-assertions
219+
list_example_harness.c
220+
$ cbmc list_example.c list_example_harness.c --function harness --unwind 20 --unwinding-assertions
172221
```
173222

174223
We have 3 new options here:
175224

176225
* `max-nondet-tree-depth` is the maximum extent to which we will generate and
177226
initialize non-null pointers - in this case, this means generating lists up to
178-
length 2
227+
length 4
179228
* `min-null-tree-depth` this is the minimum depth at which pointers can be
180229
nullpointers for generated values - in this case, this sets the _minimum_
181230
length for our linked lists to one.
@@ -205,17 +254,17 @@ We also have support for arrays (currently only for array function parameters,
205254
globals and struct members are considered for the future).
206255

207256
Take this example of an implementation of an `is_prefix_of` function that
208-
should return true if the first string parameter `string` is a prefix of the
209-
second one `prefix`.
257+
should return true if the first string parameter `prefix` is a prefix of the
258+
second one `string`.
210259

211260
```c
212261
// array_example.c
213262

214263
int is_prefix_of(
215-
const char *string,
216-
int string_length,
217264
const char *prefix,
218-
int prefix_length
265+
int prefix_length,
266+
const char *string,
267+
int string_length
219268
)
220269
{
221270
if(prefix_length > string_length) { return 0; }
@@ -239,8 +288,8 @@ $ goto-harness \
239288
--function is_prefix_of \
240289
--associated-array-size string:string_length \
241290
--associated-array-size prefix:prefix_length \
242-
array_example.gb array_example-mod.gb
243-
$ cbmc --function harness --pointer-check array_example-mod.gb
291+
array_example.gb array_example_harness.c
292+
$ cbmc --function harness --unwind 10 --pointer-check array_example_harness.c array_example.c
244293
```
245294

246295
We have the additional option `associated-array-size` here. This is in the format
@@ -250,6 +299,7 @@ the parameter `array-size-parameter-name` holding its size (it should have
250299
some integral type like `int` or `size_t`).
251300

252301
Running the example shows the bug highlighted in the comments:
302+
253303
```
254304
[...]
255305
[is_prefix_of.pointer_dereference.6] line 14 dereference failure: pointer outside object bounds in prefix[(signed long int)i]: FAILURE
@@ -282,16 +332,16 @@ void function(char *pointer, int size)
282332
283333
Then call the following:
284334
285-
```
335+
```sh
286336
$ goto-cc -o nondet_string.gb nondet_string.c
287337
$ goto-harness \
288338
--harness-function-name harness \
289339
--harness-type call-function \
290340
--function function \
291341
--treat-pointer-as-cstring pointer \
292342
--associated-array-size pointer:size \
293-
nondet_string.gb nondet_string-mod.gb
294-
$ cbmc --function harness nondet_string-mod.gb
343+
nondet_string.gb nondet_string_harness.c
344+
$ cbmc --function harness nondet_string_harness.c nondet_string.c --unwind 10
295345
```
296346

297347
Note that C strings are supported by the same mechanism
@@ -312,7 +362,13 @@ main.c function function
312362
VERIFICATION SUCCESSFUL
313363
```
314364

315-
### The memory snapshot harness
365+
## The memory snapshot harness
366+
367+
***NOTE:*** The memory snapshot harness is temporarily inoperable because of
368+
a bug that occured when we changed the implementation of `goto-harness` to
369+
produce C files instead of `goto` binaries. The bug is being tracked
370+
[here](https://github.com/diffblue/cbmc/issues/5351). We are sorry for the
371+
inconvenience, and hope to get it back to working properly soon.
316372

317373
The `function-call` harness is used in situations in which we want to analyze a
318374
function in an arbitrary environment. If we want to analyze a function starting

0 commit comments

Comments
 (0)