Skip to content

Commit 581ebb6

Browse files
author
Remi Delmas
committed
CONTRACTS: insert reachability canary asssertions
When a GOTO function has no body, insert a canary assertion to make the analysis fail in case the function is reachable.
1 parent 20535ad commit 581ebb6

File tree

7 files changed

+68
-19
lines changed

7 files changed

+68
-19
lines changed

regression/contracts-dfcc/assigns_replace_02/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <assert.h>
22

3-
void foo(int *x, int *y) __CPROVER_assigns(*x)
3+
void foo(int *x) __CPROVER_assigns(*x)
44
{
55
*x = 7;
66
}
@@ -9,7 +9,7 @@ int main()
99
{
1010
int n;
1111
int m = 4;
12-
bar(&n);
12+
foo(&n);
1313
assert(m == 4);
1414

1515
return 0;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
int foo(int);
2+
3+
int bar(int i) __CPROVER_requires(i > 0)
4+
__CPROVER_ensures(__CPROVER_return_value > 0)
5+
{
6+
return foo(i);
7+
}
8+
9+
int main()
10+
{
11+
int i;
12+
bar(i);
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--dfcc main --enforce-contract bar
4+
^\[foo.assertion.\d+\] line 1 undefined function should be unreachable: FAILURE$
5+
^VERIFICATION FAILED$
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
--
9+
--
10+
This test checks that functions without bodies result in analysis failures.

src/goto-instrument/contracts/dynamic-frames/dfcc_instrument.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@ Author: Remi Delmas, [email protected]
2222
#include <goto-programs/remove_skip.h>
2323

2424
#include <ansi-c/c_expr.h>
25+
#include <ansi-c/c_object_factory_parameters.h>
2526
#include <goto-instrument/contracts/cfg_info.h>
2627
#include <goto-instrument/contracts/contracts.h>
2728
#include <goto-instrument/contracts/utils.h>
29+
#include <goto-instrument/generate_function_bodies.h>
2830
#include <langapi/language_util.h>
2931

3032
#include "dfcc_is_freeable.h"
3133
#include "dfcc_is_fresh.h"
3234
#include "dfcc_library.h"
3335
#include "dfcc_utils.h"
3436

37+
#include <memory>
38+
3539
std::set<irep_idt> dfcc_instrumentt::function_cache;
3640

3741
dfcc_instrumentt::dfcc_instrumentt(
@@ -323,10 +327,13 @@ void dfcc_instrumentt::instrument_function_body(
323327

324328
if(!goto_function.body_available())
325329
{
326-
log.warning() << "DFCC instrumentation: '" << function_id
327-
<< "' body is not available. Results may be unsound if the "
328-
"actual function has side effects."
329-
<< messaget::eom;
330+
// generate a default body `assert(false);assume(false);`
331+
std::string options = "assert-false-assume-false";
332+
c_object_factory_parameterst object_factory_params;
333+
auto generate_function_bodies = generate_function_bodies_factory(
334+
options, object_factory_params, goto_model.symbol_table, message_handler);
335+
generate_function_bodies->generate_function_body(
336+
goto_function, goto_model.symbol_table, function_id);
330337
return;
331338
}
332339

src/goto-instrument/contracts/dynamic-frames/dfcc_library.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -469,9 +469,6 @@ void dfcc_libraryt::inhibit_front_end_builtins()
469469
const auto &fid = it.first;
470470
if(goto_model.symbol_table.has_symbol(fid))
471471
{
472-
// make sure parameter symbols exist
473-
utils.fix_parameters_symbols(fid);
474-
475472
// create fatal assertion code block as body
476473
source_locationt sl;
477474
sl.set_function(fid);
@@ -480,16 +477,7 @@ void dfcc_libraryt::inhibit_front_end_builtins()
480477
sl.set_comment(
481478
"Built-in " + id2string(fid) +
482479
" should not be called after contracts transformation");
483-
auto block = create_fatal_assertion(false_exprt(), sl);
484-
auto &symbol = goto_model.symbol_table.get_writeable_ref(fid);
485-
symbol.value = block;
486-
487-
// convert the function
488-
goto_convert(
489-
fid,
490-
goto_model.symbol_table,
491-
goto_model.goto_functions,
492-
message_handler);
480+
utils.gen_fatal_assertion_body(fid, sl);
493481
}
494482
}
495483
}

src/goto-instrument/contracts/dynamic-frames/dfcc_utils.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,28 @@ dfcc_utilst::dfcc_utilst(
4242
{
4343
}
4444

45+
void dfcc_utilst::gen_fatal_assertion_body(
46+
const irep_idt &function_id,
47+
const source_locationt &source_location)
48+
{
49+
PRECONDITION(goto_model.symbol_table.has_symbol(function_id));
50+
51+
// make sure parameter symbols exist
52+
fix_parameters_symbols(function_id);
53+
54+
// create fatal assertion code block as body
55+
auto block = create_fatal_assertion(false_exprt(), source_location);
56+
auto &symbol = goto_model.symbol_table.get_writeable_ref(function_id);
57+
symbol.value = block;
58+
59+
// convert the function
60+
goto_convert(
61+
function_id,
62+
goto_model.symbol_table,
63+
goto_model.goto_functions,
64+
message_handler);
65+
}
66+
4567
const bool dfcc_utilst::symbol_exists(
4668
const irep_idt &name,
4769
const bool require_has_code_type,

src/goto-instrument/contracts/dynamic-frames/dfcc_utils.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ class dfcc_utilst
3535
namespacet ns;
3636

3737
public:
38+
/// \brief Genrate a body `assert(false); assume(false);`
39+
/// for the given \p function_id.
40+
/// \param function_id function to generate the body for
41+
/// \param source_location source location to use for the assertion.
42+
/// Must define the property class, comment for the assertion, etc.
43+
void gen_fatal_assertion_body(
44+
const irep_idt &function_id,
45+
const source_locationt &source_location);
46+
3847
/// Returns true iff the given symbol exists and satisfies requirements.
3948
const bool symbol_exists(
4049
const irep_idt &function_id,

0 commit comments

Comments
 (0)