Skip to content

Commit bfa3212

Browse files
committed
Move rw_ok rewriting to separate pass
This reverts selected changes from "r/w/rw_ok and pointer_in_range depend on deallocated and dead_object" for transformations of goto programs can now safely introduce rw_ok expressions into the goto program.
1 parent a3d8822 commit bfa3212

File tree

16 files changed

+128
-68
lines changed

16 files changed

+128
-68
lines changed

regression/cbmc/realloc-should-not-free-on-failure-to-allocate/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE new-smt-backend
22
test.c
33
--malloc-may-fail --malloc-fail-null
4-
^\[free.precondition.\d+] line \d+ double free: SUCCESS$
4+
^\[main.precondition_instance.\d+] line \d+ double free: SUCCESS$
55
^VERIFICATION SUCCESSFUL$
66
^EXIT=0$
77
^SIGNAL=0$

regression/goto-cc-goto-analyzer/instrument_preconditions_locations/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ test.c
44
^EXIT=0$
55
^SIGNAL=0$
66
Checking assertions
7-
^\[free.precondition.1\] line \d+ free argument must be NULL or valid pointer: SUCCESS
7+
^\[EVP_MD_CTX_free.precondition_instance.1\] line \d+ free argument must be NULL or valid pointer: SUCCESS
88
--
99
Invariant check failed
1010
--

src/cbmc/cbmc_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ void cbmc_parse_optionst::get_command_line_options(optionst &options)
406406
PARSE_OPTIONS_GOTO_TRACE(cmdline, options);
407407

408408
// Options for process_goto_program
409+
options.set_option("rewrite-rw-ok", true);
409410
options.set_option("rewrite-union", true);
410411

411412
if(cmdline.isset("smt1"))

src/cprover/state_encoding.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -294,20 +294,6 @@ exprt state_encodingt::evaluate_expr_rec(
294294
: ID_state_rw_ok;
295295
return ternary_exprt(new_id, state, pointer, size, what.type());
296296
}
297-
else if(
298-
const auto r_or_w_ok_expr =
299-
expr_try_dynamic_cast<prophecy_r_or_w_ok_exprt>(what))
300-
{
301-
// we replace prophecy expressions by our state
302-
auto pointer =
303-
evaluate_expr_rec(loc, state, r_or_w_ok_expr->pointer(), bound_symbols);
304-
auto size =
305-
evaluate_expr_rec(loc, state, r_or_w_ok_expr->size(), bound_symbols);
306-
auto new_id = what.id() == ID_prophecy_r_ok ? ID_state_r_ok
307-
: what.id() == ID_prophecy_w_ok ? ID_state_w_ok
308-
: ID_state_rw_ok;
309-
return ternary_exprt(new_id, state, pointer, size, what.type());
310-
}
311297
else if(what.id() == ID_is_cstring)
312298
{
313299
// we need to add the state

src/goto-analyzer/goto_analyzer_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ int goto_analyzer_parse_optionst::doit()
393393

394394
// Preserve backwards compatibility in processing
395395
options.set_option("partial-inline", true);
396+
options.set_option("rewrite-rw-ok", false);
396397
options.set_option("rewrite-union", false);
397398
options.set_option("remove-returns", true);
398399

src/goto-diff/goto_diff_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ void goto_diff_parse_optionst::get_command_line_options(optionst &options)
6565
options.set_option("show-properties", cmdline.isset("show-properties"));
6666

6767
// Options for process_goto_program
68+
options.set_option("rewrite-rw-ok", false);
6869
options.set_option("rewrite-union", true);
6970
}
7071

src/goto-instrument/contracts/instrument_spec_assigns.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,13 +644,9 @@ exprt instrument_spec_assignst::target_validity_expr(
644644
// (or is NULL if we allow it explicitly).
645645
// This assertion will be falsified whenever `start_address` is invalid or
646646
// not of the right size (or is NULL if we do not allow it explicitly).
647-
symbol_exprt deallocated =
648-
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr();
649-
symbol_exprt dead = ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
650-
auto result = or_exprt{
651-
not_exprt{car.condition()},
652-
prophecy_w_ok_exprt{
653-
car.target_start_address(), car.target_size(), deallocated, dead}};
647+
auto result =
648+
or_exprt{not_exprt{car.condition()},
649+
w_ok_exprt{car.target_start_address(), car.target_size()}};
654650

655651
if(allow_null_target)
656652
result.add_to_operands(null_object(car.target_start_address()));

src/goto-instrument/contracts/utils.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,7 @@ exprt all_dereferences_are_valid(const exprt &expr, const namespacet &ns)
178178
const auto size_of_expr_opt = size_of_expr(expr.type(), ns);
179179
CHECK_RETURN(size_of_expr_opt.has_value());
180180

181-
symbol_exprt deallocated =
182-
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr();
183-
symbol_exprt dead = ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
184-
validity_checks.push_back(prophecy_r_ok_exprt{
185-
deref->pointer(), *size_of_expr_opt, deallocated, dead});
181+
validity_checks.push_back(r_ok_exprt{deref->pointer(), *size_of_expr_opt});
186182
}
187183

188184
for(const auto &op : expr.operands())

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Author: Daniel Kroening, [email protected]
4545
#include <goto-programs/remove_unused_functions.h>
4646
#include <goto-programs/remove_virtual_functions.h>
4747
#include <goto-programs/restrict_function_pointers.h>
48+
#include <goto-programs/rewrite_rw_ok.h>
4849
#include <goto-programs/rewrite_union.h>
4950
#include <goto-programs/set_properties.h>
5051
#include <goto-programs/show_properties.h>
@@ -1767,6 +1768,7 @@ void goto_instrument_parse_optionst::instrument_goto_program()
17671768
{
17681769
do_indirect_call_and_rtti_removal();
17691770
do_remove_returns();
1771+
rewrite_rw_ok(goto_model);
17701772

17711773
log.warning() << "**** WARNING: Experimental option --full-slice, "
17721774
<< "analysis results may be unsound. See "

src/goto-programs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ SRC = allocate_objects.cpp \
5656
remove_vector.cpp \
5757
remove_virtual_functions.cpp \
5858
restrict_function_pointers.cpp \
59+
rewrite_rw_ok.cpp \
5960
rewrite_union.cpp \
6061
resolve_inherited_component.cpp \
6162
safety_checker.cpp \

src/goto-programs/builtin_functions.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -669,10 +669,7 @@ void goto_convertt::do_havoc_slice(
669669
// char nondet_contents[argument[1]];
670670
// __CPROVER_array_replace(p, nondet_contents);
671671

672-
symbol_exprt deallocated =
673-
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr();
674-
symbol_exprt dead = ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
675-
prophecy_w_ok_exprt ok_expr{arguments[0], arguments[1], deallocated, dead};
672+
r_or_w_ok_exprt ok_expr(ID_w_ok, arguments[0], arguments[1]);
676673
ok_expr.add_source_location() = source_location;
677674
source_locationt annotated_location = source_location;
678675
annotated_location.set("user-provided", false);

src/goto-programs/goto_clean_expr.cpp

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

1212
#include "goto_convert_class.h"
1313

14-
#include <util/cprover_prefix.h>
1514
#include <util/expr_util.h>
1615
#include <util/fresh_symbol.h>
1716
#include <util/pointer_expr.h>
@@ -74,15 +73,6 @@ bool goto_convertt::needs_cleaning(const exprt &expr)
7473
return true;
7574
}
7675

77-
// Rewrite rw_ok and pointer_in_range front-end expressions into ones
78-
// including prophecy expressions.
79-
if(
80-
can_cast_expr<r_or_w_ok_exprt>(expr) ||
81-
can_cast_expr<pointer_in_range_exprt>(expr))
82-
{
83-
return true;
84-
}
85-
8676
// We can't flatten quantified expressions by introducing new literals for
8777
// conditional expressions. This is because the body of the quantified
8878
// may refer to bound variables, which are not visible outside the scope
@@ -446,32 +436,6 @@ void goto_convertt::clean_expr(
446436
expr.operands().size() == 1, "ID_compound_literal has a single operand");
447437
expr = to_unary_expr(expr).op();
448438
}
449-
else if(auto r_or_w_ok = expr_try_dynamic_cast<r_or_w_ok_exprt>(expr))
450-
{
451-
const auto &id = expr.id();
452-
expr =
453-
prophecy_r_or_w_ok_exprt{
454-
id == ID_r_ok ? ID_prophecy_r_ok
455-
: id == ID_w_ok ? ID_prophecy_w_ok
456-
: ID_prophecy_rw_ok,
457-
r_or_w_ok->pointer(),
458-
r_or_w_ok->size(),
459-
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr(),
460-
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr()}
461-
.with_source_location<exprt>(expr);
462-
}
463-
else if(
464-
auto pointer_in_range = expr_try_dynamic_cast<pointer_in_range_exprt>(expr))
465-
{
466-
expr =
467-
prophecy_pointer_in_range_exprt{
468-
pointer_in_range->lower_bound(),
469-
pointer_in_range->pointer(),
470-
pointer_in_range->upper_bound(),
471-
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr(),
472-
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr()}
473-
.with_source_location<exprt>(expr);
474-
}
475439
}
476440

477441
void goto_convertt::clean_expr_address_of(

src/goto-programs/process_goto_program.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Martin Brain, [email protected]
2323
#include <goto-programs/remove_function_pointers.h>
2424
#include <goto-programs/remove_returns.h>
2525
#include <goto-programs/remove_vector.h>
26+
#include <goto-programs/rewrite_rw_ok.h>
2627
#include <goto-programs/rewrite_union.h>
2728
#include <goto-programs/string_abstraction.h>
2829
#include <goto-programs/string_instrumentation.h>
@@ -70,6 +71,9 @@ bool process_goto_program(
7071
if(options.get_bool_option("rewrite-union"))
7172
rewrite_union(goto_model);
7273

74+
if(options.get_bool_option("rewrite-rw-ok"))
75+
rewrite_rw_ok(goto_model);
76+
7377
// add generic checks
7478
log.status() << "Generic Property Instrumentation" << messaget::eom;
7579
goto_check_c(options, goto_model, log.get_message_handler());

src/goto-programs/rewrite_rw_ok.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*******************************************************************\
2+
3+
Module: Rewrite {r,w,rw}_ok expressions as required by symbolic execution
4+
5+
Author: Michael Tautschnig
6+
7+
\*******************************************************************/
8+
9+
#include "rewrite_rw_ok.h"
10+
11+
#include <util/expr_iterator.h>
12+
#include <util/pointer_expr.h>
13+
14+
#include <goto-programs/goto_model.h>
15+
16+
static optionalt<exprt> rewrite_rw_ok(exprt expr, const namespacet &ns)
17+
{
18+
bool unchanged = true;
19+
20+
for(auto it = expr.depth_begin(), itend = expr.depth_end();
21+
it != itend;) // no ++it
22+
{
23+
if(auto r_or_w_ok = expr_try_dynamic_cast<r_or_w_ok_exprt>(*it))
24+
{
25+
const auto &id = it->id();
26+
exprt replacement =
27+
prophecy_r_or_w_ok_exprt{
28+
id == ID_r_ok ? ID_prophecy_r_ok
29+
: id == ID_w_ok ? ID_prophecy_w_ok
30+
: ID_prophecy_rw_ok,
31+
r_or_w_ok->pointer(),
32+
r_or_w_ok->size(),
33+
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr(),
34+
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr()}
35+
.with_source_location<exprt>(*it);
36+
37+
it.mutate() = std::move(replacement);
38+
unchanged = false;
39+
it.next_sibling_or_parent();
40+
}
41+
else if(
42+
auto pointer_in_range =
43+
expr_try_dynamic_cast<pointer_in_range_exprt>(*it))
44+
{
45+
exprt replacement =
46+
prophecy_pointer_in_range_exprt{
47+
pointer_in_range->lower_bound(),
48+
pointer_in_range->pointer(),
49+
pointer_in_range->upper_bound(),
50+
ns.lookup(CPROVER_PREFIX "deallocated").symbol_expr(),
51+
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr()}
52+
.with_source_location<exprt>(*it);
53+
54+
it.mutate() = std::move(replacement);
55+
unchanged = false;
56+
it.next_sibling_or_parent();
57+
}
58+
else
59+
++it;
60+
}
61+
62+
if(unchanged)
63+
return {};
64+
else
65+
return std::move(expr);
66+
}
67+
68+
static void rewrite_rw_ok(
69+
goto_functionst::goto_functiont &goto_function,
70+
const namespacet &ns)
71+
{
72+
for(auto &instruction : goto_function.body.instructions)
73+
instruction.transform(
74+
[&ns](exprt expr) { return rewrite_rw_ok(expr, ns); });
75+
}
76+
77+
void rewrite_rw_ok(goto_modelt &goto_model)
78+
{
79+
const namespacet ns(goto_model.symbol_table);
80+
81+
for(auto &gf_entry : goto_model.goto_functions.function_map)
82+
rewrite_rw_ok(gf_entry.second, ns);
83+
}

src/goto-programs/rewrite_rw_ok.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*******************************************************************\
2+
3+
Module: Rewrite {r,w,rw}_ok expressions as required by symbolic execution
4+
5+
Author: Michael Tautschnig
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Rewrite r/w/rw_ok expressions to ones including prophecy variables recording
11+
/// the state.
12+
13+
#ifndef CPROVER_GOTO_PROGRAMS_REWRITE_RW_OK_H
14+
#define CPROVER_GOTO_PROGRAMS_REWRITE_RW_OK_H
15+
16+
class goto_modelt;
17+
18+
/// Replace all occurrences of `r_ok_exprt`, `w_ok_exprt`, `rw_ok_exprt`,
19+
/// `pointer_in_range_exprt` by their prophecy variants
20+
/// `prophecy_r_or_w_ok_exprt` and `prophecy_pointer_in_range_exprt`,
21+
/// respectively.
22+
/// Each analysis may choose to natively support `r_ok_exprt` etc. (like
23+
/// `cprover_parse_optionst` does) or may instead require the expression to be
24+
/// lowered to other primitives (like `goto_symext`).
25+
void rewrite_rw_ok(goto_modelt &);
26+
27+
#endif // CPROVER_GOTO_PROGRAMS_REWRITE_RW_OK_H

src/goto-synthesizer/goto_synthesizer_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ optionst goto_synthesizer_parse_optionst::get_options()
199199
options.set_option("depth", UINT32_MAX);
200200
options.set_option("exploration-strategy", "lifo");
201201
options.set_option("symex-cache-dereferences", false);
202+
options.set_option("rewrite-rw-ok", true);
202203
options.set_option("rewrite-union", true);
203204
options.set_option("self-loops-to-assumptions", true);
204205

0 commit comments

Comments
 (0)