1
1
[ CPROVER Manual TOC] ( ../../ )
2
2
3
- ## Goto Harness
3
+ # Goto Harness
4
4
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
6
6
another function under analysis, by setting up an appropriate environment before
7
7
calling them.
8
8
9
9
This is useful when trying to analyse an isolated unit of a program without
10
10
having to manually construct an appropriate environment.
11
11
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
13
27
14
28
We have two types of harnesses we can generate for now:
15
29
@@ -18,6 +32,9 @@ without having any information about the program state.
18
32
* The ` memory-snapshot ` harness, which loads an existing program state (in form
19
33
of a JSON file) and selectively _ havoc-ing_ some variables.
20
34
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
+
21
38
It is used similarly to how ` goto-instrument ` is used by modifying an existing
22
39
GOTO binary, as produced by ` goto-cc ` .
23
40
@@ -45,15 +62,15 @@ $ goto-cc -o main.gb main.c
45
62
```
46
63
47
64
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:
49
66
50
67
``` sh
51
68
$ goto-harness \
52
69
--harness-function-name harness \
53
70
--harness-type call-function \
54
71
--function function_to_test \
55
72
main.gb \
56
- main-with- harness.gb
73
+ harness.c
57
74
```
58
75
59
76
The options we pass to ` goto-harness ` are:
@@ -63,34 +80,66 @@ The options we pass to `goto-harness` are:
63
80
* ` harness-type ` is the type of harness to generate (` call-function ` is the
64
81
function-call harness generator)
65
82
* ` 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 .
67
84
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:
70
86
71
87
``` 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)
77
108
{
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);
80
112
}
81
113
82
- void harness(void)
114
+ // type_constructor_int
115
+ //
116
+ void type_constructor_int(signed int depth_int, signed int * result_int)
83
117
{
84
- int argument = nondet_int() ;
85
- function_to_test(argument) ;
118
+ signed int nondet ;
119
+ * result_int = nondet ;
86
120
}
87
121
```
88
122
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 ` ).
92
139
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
94
143
as the entry point ` cbmc ` automatically generates for functions. However, the
95
144
` function-call ` harness can also non-deterministically initialise global
96
145
variables, array and struct elements. Consider this more complicated example:
@@ -167,15 +216,15 @@ $ goto-harness \
167
216
--min-null-tree-depth 1 \
168
217
--nondet-globals \
169
218
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
172
221
```
173
222
174
223
We have 3 new options here:
175
224
176
225
* ` max-nondet-tree-depth ` is the maximum extent to which we will generate and
177
226
initialize non-null pointers - in this case, this means generating lists up to
178
- length 2
227
+ length 4
179
228
* ` min-null-tree-depth ` this is the minimum depth at which pointers can be
180
229
nullpointers for generated values - in this case, this sets the _ minimum_
181
230
length for our linked lists to one.
@@ -205,17 +254,17 @@ We also have support for arrays (currently only for array function parameters,
205
254
globals and struct members are considered for the future).
206
255
207
256
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 ` .
210
259
211
260
``` c
212
261
// array_example.c
213
262
214
263
int is_prefix_of (
215
- const char * string,
216
- int string_length,
217
264
const char * prefix,
218
- int prefix_length
265
+ int prefix_length,
266
+ const char * string,
267
+ int string_length
219
268
)
220
269
{
221
270
if(prefix_length > string_length) { return 0; }
@@ -239,8 +288,8 @@ $ goto-harness \
239
288
--function is_prefix_of \
240
289
--associated-array-size string:string_length \
241
290
--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
244
293
```
245
294
246
295
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
250
299
some integral type like ` int ` or ` size_t ` ).
251
300
252
301
Running the example shows the bug highlighted in the comments:
302
+
253
303
```
254
304
[...]
255
305
[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)
282
332
283
333
Then call the following:
284
334
285
- ```
335
+ ```sh
286
336
$ goto-cc -o nondet_string.gb nondet_string.c
287
337
$ goto-harness \
288
338
--harness-function-name harness \
289
339
--harness-type call-function \
290
340
--function function \
291
341
--treat-pointer-as-cstring pointer \
292
342
--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
295
345
```
296
346
297
347
Note that C strings are supported by the same mechanism
@@ -312,7 +362,13 @@ main.c function function
312
362
VERIFICATION SUCCESSFUL
313
363
```
314
364
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.
316
372
317
373
The ` function-call ` harness is used in situations in which we want to analyze a
318
374
function in an arbitrary environment. If we want to analyze a function starting
0 commit comments