@@ -65,6 +65,8 @@ SCENARIO("path strategies")
65
65
std::string c;
66
66
GIVEN (" a simple conditional program" )
67
67
{
68
+ std::function<void (optionst &)> opts_callback = [](optionst &opts) {};
69
+
68
70
c =
69
71
" /* 1 */ int main() \n "
70
72
" /* 2 */ { \n "
@@ -75,28 +77,28 @@ SCENARIO("path strategies")
75
77
" /* 7 */ x = 0; \n "
76
78
" /* 8 */ } \n " ;
77
79
78
- const unsigned unwind_limit = 0U ;
79
-
80
80
check_with_strategy (
81
81
" lifo" ,
82
+ opts_callback,
82
83
c,
83
84
{symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
84
85
symex_eventt::result (symex_eventt::enumt::SUCCESS),
85
86
symex_eventt::resume (symex_eventt::enumt::NEXT, 5 ),
86
- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
87
- unwind_limit);
87
+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
88
88
check_with_strategy (
89
89
" fifo" ,
90
+ opts_callback,
90
91
c,
91
92
{symex_eventt::resume (symex_eventt::enumt::NEXT, 5 ),
92
93
symex_eventt::result (symex_eventt::enumt::SUCCESS),
93
94
symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
94
- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
95
- unwind_limit);
95
+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
96
96
}
97
97
98
98
GIVEN (" a program with nested conditionals" )
99
99
{
100
+ std::function<void (optionst &)> opts_callback = [](optionst &opts) {};
101
+
100
102
c =
101
103
" /* 1 */ int main() \n "
102
104
" /* 2 */ { \n "
@@ -117,10 +119,9 @@ SCENARIO("path strategies")
117
119
" /* 17 */ } \n "
118
120
" /* 18 */ } \n " ;
119
121
120
- const unsigned unwind_limit = 0U ;
121
-
122
122
check_with_strategy (
123
123
" lifo" ,
124
+ opts_callback,
124
125
c,
125
126
{// Outer else, inner else
126
127
symex_eventt::resume (symex_eventt::enumt::JUMP, 13 ),
@@ -135,11 +136,11 @@ SCENARIO("path strategies")
135
136
symex_eventt::result (symex_eventt::enumt::SUCCESS),
136
137
// Outer if, inner if
137
138
symex_eventt::resume (symex_eventt::enumt::NEXT, 7 ),
138
- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
139
- unwind_limit);
139
+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
140
140
141
141
check_with_strategy (
142
142
" fifo" ,
143
+ opts_callback,
143
144
c,
144
145
{// Expand outer if, but don't continue depth-first
145
146
symex_eventt::resume (symex_eventt::enumt::NEXT, 6 ),
@@ -155,12 +156,15 @@ SCENARIO("path strategies")
155
156
symex_eventt::resume (symex_eventt::enumt::NEXT, 14 ),
156
157
symex_eventt::result (symex_eventt::enumt::SUCCESS),
157
158
symex_eventt::resume (symex_eventt::enumt::JUMP, 16 ),
158
- symex_eventt::result (symex_eventt::enumt::SUCCESS)},
159
- unwind_limit);
159
+ symex_eventt::result (symex_eventt::enumt::SUCCESS)});
160
160
}
161
161
162
162
GIVEN (" a loop program to test functional correctness" )
163
163
{
164
+ std::function<void (optionst &)> opts_callback = [](optionst &opts) {
165
+ opts.set_option (" unwind" , 2U );
166
+ };
167
+
164
168
c =
165
169
" /* 1 */ int main() \n "
166
170
" /* 2 */ { \n "
@@ -173,10 +177,9 @@ SCENARIO("path strategies")
173
177
" /* 9 */ assert(x); \n "
174
178
" /* 10 */ } \n " ;
175
179
176
- const unsigned unwind_limit = 2U ;
177
-
178
180
check_with_strategy (
179
181
" lifo" ,
182
+ opts_callback,
180
183
c,
181
184
{
182
185
// The path where we skip the loop body. Successful because the path is
@@ -194,11 +197,11 @@ SCENARIO("path strategies")
194
197
// infeasible.
195
198
symex_eventt::resume (symex_eventt::enumt::NEXT, 7 ),
196
199
symex_eventt::result (symex_eventt::enumt::SUCCESS),
197
- },
198
- unwind_limit);
200
+ });
199
201
200
202
check_with_strategy (
201
203
" fifo" ,
204
+ opts_callback,
202
205
c,
203
206
{
204
207
// The path where we skip the loop body. Successful because the path is
@@ -219,8 +222,46 @@ SCENARIO("path strategies")
219
222
// executing the loop once, decrementing x to 0; assert(x) should fail.
220
223
symex_eventt::resume (symex_eventt::enumt::JUMP, 9 ),
221
224
symex_eventt::result (symex_eventt::enumt::FAILURE),
222
- },
223
- unwind_limit);
225
+ });
226
+ }
227
+
228
+ GIVEN (" program to check for stop-on-fail with path exploration" )
229
+ {
230
+ std::function<void (optionst &)> halt_callback = [](optionst &opts) {
231
+ opts.set_option (" stop-on-fail" , true );
232
+ };
233
+ std::function<void (optionst &)> no_halt_callback = [](optionst &opts) {};
234
+
235
+ c =
236
+ " /* 1 */ int main() \n "
237
+ " /* 2 */ { \n "
238
+ " /* 3 */ int x, y; \n "
239
+ " /* 4 */ if(x) \n "
240
+ " /* 5 */ assert(0); \n "
241
+ " /* 6 */ else \n "
242
+ " /* 7 */ assert(0); \n "
243
+ " /* 8 */ } \n " ;
244
+
245
+ GIVEN (" no stopping on failure" )
246
+ {
247
+ check_with_strategy (
248
+ " lifo" ,
249
+ no_halt_callback,
250
+ c,
251
+ {symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
252
+ symex_eventt::result (symex_eventt::enumt::FAILURE),
253
+ symex_eventt::resume (symex_eventt::enumt::NEXT, 5 ),
254
+ symex_eventt::result (symex_eventt::enumt::FAILURE)});
255
+ }
256
+ GIVEN (" stopping on failure" )
257
+ {
258
+ check_with_strategy (
259
+ " lifo" ,
260
+ halt_callback,
261
+ c,
262
+ {symex_eventt::resume (symex_eventt::enumt::JUMP, 7 ),
263
+ symex_eventt::result (symex_eventt::enumt::FAILURE)});
264
+ }
224
265
}
225
266
}
226
267
@@ -286,7 +327,7 @@ void symex_eventt::validate_resume(
286
327
void _check_with_strategy (
287
328
const std::string &strategy,
288
329
const std::string &program,
289
- const unsigned unwind_limit ,
330
+ std::function< void (optionst &)> opts_callback ,
290
331
symex_eventt::listt &events)
291
332
{
292
333
temporary_filet tmp (" path-explore_" , " .c" );
@@ -307,11 +348,7 @@ void _check_with_strategy(
307
348
opts.set_option (" paths" , true );
308
349
opts.set_option (" exploration-strategy" , strategy);
309
350
310
- if (unwind_limit)
311
- {
312
- opts.set_option (" unwind" , unwind_limit);
313
- cmdline.set (" unwind" , std::to_string (unwind_limit));
314
- }
351
+ opts_callback (opts);
315
352
316
353
ui_message_handlert mh (cmdline, " path-explore" );
317
354
mh.set_verbosity (0 );
@@ -337,6 +374,13 @@ void _check_with_strategy(
337
374
safety_checkert::resultt result = bmc.run (gm);
338
375
symex_eventt::validate_result (events, result);
339
376
377
+ if (
378
+ result == safety_checkert::resultt::UNSAFE &&
379
+ opts.get_bool_option (" stop-on-fail" ) && opts.is_set (" paths" ))
380
+ {
381
+ worklist->clear ();
382
+ }
383
+
340
384
while (!worklist->empty ())
341
385
{
342
386
cbmc_solverst solvers (opts, gm.get_symbol_table (), mh);
@@ -360,6 +404,13 @@ void _check_with_strategy(
360
404
361
405
symex_eventt::validate_result (events, result);
362
406
worklist->pop ();
407
+
408
+ if (
409
+ result == safety_checkert::resultt::UNSAFE &&
410
+ opts.get_bool_option (" stop-on-fail" ))
411
+ {
412
+ worklist->clear ();
413
+ }
363
414
}
364
415
REQUIRE (events.empty ());
365
416
}
0 commit comments