Skip to content

Commit 4fe774e

Browse files
committed
Havoc undefined functions during symbolic execution
This havocs any modifiable arguments passed to undefined functions at symex time. It is enabled by --havoc-undefined-functions
1 parent d453933 commit 4fe774e

File tree

9 files changed

+57
-2
lines changed

9 files changed

+57
-2
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
void function(int *a);
2+
3+
int main()
4+
{
5+
int a = 0;
6+
function(&a);
7+
__CPROVER_assert(a == 0, "");
8+
return 0;
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
main.c
3+
--havoc-undefined-functions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$

src/cbmc/cbmc_parse_options.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
240240
if(cmdline.isset("drop-unused-functions"))
241241
options.set_option("drop-unused-functions", true);
242242

243+
if(cmdline.isset("havoc-undefined-functions"))
244+
options.set_option("havoc-undefined-functions", true);
245+
243246
if(cmdline.isset("string-abstraction"))
244247
options.set_option("string-abstraction", true);
245248

@@ -1082,6 +1085,9 @@ void cbmc_parse_optionst::help()
10821085
HELP_REACHABILITY_SLICER_FB
10831086
" --full-slice run full slicer (experimental)\n" // NOLINT(*)
10841087
" --drop-unused-functions drop functions trivially unreachable from main function\n" // NOLINT(*)
1088+
" --havoc-undefined-functions\n"
1089+
" for any function that has no body, assign non-deterministic values to\n" // NOLINT(*)
1090+
" any parameters passed as non-const pointers and the return value\n" // NOLINT(*)
10851091
"\n"
10861092
"Semantic transformations:\n"
10871093
// NOLINTNEXTLINE(whitespace/line_length)

src/cbmc/cbmc_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class optionst;
6767
OPT_SHOW_PROPERTIES \
6868
"(show-symbol-table)(show-parse-tree)" \
6969
"(drop-unused-functions)" \
70+
"(havoc-undefined-functions)" \
7071
"(property):(stop-on-fail)(trace)" \
7172
"(error-label):(verbosity):(no-library)" \
7273
"(nondet-static)" \

src/goto-checker/symex_bmc.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ symex_bmct::symex_bmct(
3333
path_storage,
3434
guard_manager),
3535
record_coverage(!options.get_option("symex-coverage-report").empty()),
36+
havoc_bodyless_functions(
37+
options.get_bool_option("havoc-undefined-functions")),
3638
symex_coverage(ns)
3739
{
3840
}
@@ -210,7 +212,13 @@ void symex_bmct::no_body(const irep_idt &identifier)
210212
{
211213
if(body_warnings.insert(identifier).second)
212214
{
213-
log.warning() << "**** WARNING: no body for function " << identifier
214-
<< log.eom;
215+
log.warning() << "**** WARNING: no body for function " << identifier;
216+
217+
if(havoc_bodyless_functions)
218+
{
219+
log.warning()
220+
<< "; assigning non-deterministic values to any pointer arguments";
221+
}
222+
log.warning() << log.eom;
215223
}
216224
}

src/goto-checker/symex_bmc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class symex_bmct : public goto_symext
8181
}
8282

8383
const bool record_coverage;
84+
const bool havoc_bodyless_functions;
8485

8586
unwindsett unwindset;
8687

src/goto-symex/symex_config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ struct symex_configt final
3434

3535
bool partial_loops;
3636

37+
bool havoc_undefined_functions;
38+
3739
mp_integer debug_level;
3840

3941
/// \brief Should the additional validation checks be run?

src/goto-symex/symex_function_call.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "goto_symex.h"
1313

14+
#include <analyses/guard_expr.h>
1415
#include <util/arith_tools.h>
1516
#include <util/byte_operators.h>
1617
#include <util/c_types.h>
@@ -293,6 +294,25 @@ void goto_symext::symex_function_call_code(
293294
symex_assign(state, code);
294295
}
295296

297+
if(symex_config.havoc_undefined_functions)
298+
{
299+
// assign non det to function arguments if pointers
300+
// are not const
301+
for(const auto &arg : call.arguments())
302+
{
303+
if(
304+
arg.type().id() == ID_pointer &&
305+
!arg.type().subtype().get_bool(ID_C_constant) &&
306+
arg.type().subtype().id() != ID_code)
307+
{
308+
exprt object = dereference_exprt(arg, arg.type().subtype());
309+
exprt cleaned_object = clean_expr(object, state, true);
310+
const guardt guard(true_exprt(), state.guard_manager);
311+
havoc_rec(state, guard, cleaned_object);
312+
}
313+
}
314+
}
315+
296316
symex_transition(state);
297317
return;
298318
}

src/goto-symex/symex_main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ symex_configt::symex_configt(const optionst &options)
4242
simplify_opt(options.get_bool_option("simplify")),
4343
unwinding_assertions(options.get_bool_option("unwinding-assertions")),
4444
partial_loops(options.get_bool_option("partial-loops")),
45+
havoc_undefined_functions(
46+
options.get_bool_option("havoc-undefined-functions")),
4547
debug_level(unsafe_string2int(options.get_option("debug-level"))),
4648
run_validation_checks(options.get_bool_option("validate-ssa-equation")),
4749
show_symex_steps(options.get_bool_option("show-goto-symex-steps")),

0 commit comments

Comments
 (0)