Skip to content

Commit 1689495

Browse files
committed
Track deallocated/dead in an array
This enables tracking of all deallocations and all dead objects, and thereby use of deallocated/dead_object predicates within assumptions.
1 parent 4e17a5d commit 1689495

File tree

13 files changed

+54
-37
lines changed

13 files changed

+54
-37
lines changed

regression/cbmc/array_of_bool_as_bitvec/test-smt2-outfile.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
CORE broken-smt-backend
22
main.c
33
--smt2 --outfile -
4-
\(= \(select array_of\.2 i\) \(ite false #b1 #b0\)\)
4+
\(= \(select array_of\.\d+ i\) \(ite false #b1 #b0\)\)
55
\(= \(select array\.3 \(\(_ zero_extend 32\) \|main::1::idx!0@1#1\|\)\) #b1\)
66
\(= \(select array\.3 \(_ bv\d+ 64\)\) \(ite false #b1 #b0\)\)
77
^EXIT=0$
88
^SIGNAL=0$
99
--
10-
\(= \(select array_of\.2 i\) false\)
10+
\(= \(select array_of\.\d+ i\) false\)
1111
\(= \(select array\.3 \(\(_ zero_extend 32\) \|main::1::idx!0@1#1\|\)\) #b1 #b0\)
1212
\(= \(select array\.3 \(_ bv\d+ 64\)\) false\)
1313
--

regression/cbmc/pointer-extra-checks/test.desc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ main.c
1010
^\[main.pointer_dereference.5\] .* dereference failure: pointer outside dynamic object bounds in \*r: SUCCESS$
1111
^\[main.pointer_dereference.6\] .* dereference failure: pointer NULL in \*s: FAILURE$
1212
^\[main.pointer_dereference.7\] .* dereference failure: pointer invalid in \*s: FAILURE$
13-
^\[main.pointer_dereference.8\] .* dereference failure: deallocated dynamic object in \*s: FAILURE$
1413
^\[main.pointer_dereference.9\] .* dereference failure: dead object in \*s: FAILURE$
1514
^\[main.pointer_dereference.10\] .* dereference failure: pointer outside object bounds in \*s: FAILURE$
1615
^\[main.pointer_dereference.11\] .* dereference failure: invalid integer address in \*s: FAILURE$

regression/cbmc/r_w_ok10/main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <stdlib.h>
2+
3+
int main()
4+
{
5+
int *p = malloc(sizeof(int));
6+
free(p);
7+
__CPROVER_assume(__CPROVER_r_ok(p, sizeof(int)));
8+
__CPROVER_assert(0, "should be unreachable");
9+
}

regression/cbmc/r_w_ok10/test.desc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
4+
VERIFICATION SUCCESSFUL
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
This test checks that __CPROVER_r_ok can safely be used in assumptions.

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
22
test.c
33
--malloc-may-fail --malloc-fail-null
4-
^\[main.precondition_instance.\d+] line \d+ double free: SUCCESS$
4+
^\[(free.precondition|main.precondition_instance).\d+] line \d+ double free: SUCCESS$
55
^VERIFICATION SUCCESSFUL$
66
^EXIT=0$
77
^SIGNAL=0$

src/ansi-c/ansi_c_internal_additions.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ void ansi_c_internal_additions(std::string &code)
171171
CPROVER_PREFIX "constant_infinity_uint];\n"
172172

173173
// malloc
174-
"const void *" CPROVER_PREFIX "deallocated=0;\n"
175-
"const void *" CPROVER_PREFIX "dead_object=0;\n"
174+
CPROVER_PREFIX "bool " CPROVER_PREFIX "deallocated["
175+
CPROVER_PREFIX "constant_infinity_uint];\n"
176+
CPROVER_PREFIX "bool " CPROVER_PREFIX "dead_object["
177+
CPROVER_PREFIX "constant_infinity_uint];\n"
176178
"const void *" CPROVER_PREFIX "new_object=0;\n" // for C++
177179
CPROVER_PREFIX "bool " CPROVER_PREFIX "malloc_is_new_array=0;\n" // for C++
178180
"const void *" CPROVER_PREFIX "memory_leak=0;\n"

src/ansi-c/goto_check_c.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,15 +2214,9 @@ void goto_check_ct::goto_check(
22142214
if(local_bitvector_analysis->dirty(variable))
22152215
{
22162216
// need to mark the dead variable as dead
2217-
exprt lhs = ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
2218-
exprt address_of_expr = typecast_exprt::conditional_cast(
2219-
address_of_exprt(variable), lhs.type());
2220-
if_exprt rhs(
2221-
side_effect_expr_nondett(bool_typet(), i.source_location()),
2222-
std::move(address_of_expr),
2223-
lhs);
2217+
exprt lhs = dead_object(address_of_exprt{variable}, ns);
22242218
new_code.add(goto_programt::make_assignment(
2225-
code_assignt{std::move(lhs), std::move(rhs), i.source_location()},
2219+
code_assignt{std::move(lhs), true_exprt{}, i.source_location()},
22262220
i.source_location()));
22272221
}
22282222
}

src/ansi-c/library/cprover.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ typedef signed long long __CPROVER_ssize_t;
2020

2121
void *__CPROVER_allocate(__CPROVER_size_t size, __CPROVER_bool zero);
2222
void __CPROVER_deallocate(void *);
23-
extern const void *__CPROVER_deallocated;
23+
extern __CPROVER_bool __CPROVER_deallocated[];
2424
extern const void *__CPROVER_new_object;
2525
extern __CPROVER_bool __CPROVER_malloc_is_new_array;
2626
extern const void *__CPROVER_memory_leak;

src/ansi-c/library/stdlib.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,9 @@ void free(void *ptr)
264264
"free argument has offset zero");
265265

266266
// catch double free
267-
__CPROVER_precondition(ptr==0 || __CPROVER_deallocated!=ptr,
268-
"double free");
267+
__CPROVER_precondition(
268+
ptr == 0 || !__CPROVER_deallocated[__CPROVER_POINTER_OBJECT(ptr)],
269+
"double free");
269270

270271
// catch people who try to use free(...) for stuff
271272
// allocated with new[]
@@ -602,10 +603,7 @@ __CPROVER_HIDE:;
602603

603604
/* FUNCTION: __CPROVER_deallocate */
604605

605-
__CPROVER_bool __VERIFIER_nondet___CPROVER_bool();
606-
607606
void __CPROVER_deallocate(void *ptr)
608607
{
609-
if(__VERIFIER_nondet___CPROVER_bool())
610-
__CPROVER_deallocated = ptr;
608+
__CPROVER_deallocated[__CPROVER_POINTER_OBJECT(ptr)] = 1;
611609
}

src/cpp/cpp_internal_additions.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@ void cpp_internal_additions(std::ostream &out)
8888
<< CPROVER_PREFIX "memory[__CPROVER::constant_infinity_uint];" << '\n';
8989

9090
// malloc
91-
out << "const void *" CPROVER_PREFIX "deallocated = 0;" << '\n';
92-
out << "const void *" CPROVER_PREFIX "dead_object = 0;" << '\n';
91+
out << CPROVER_PREFIX "bool "
92+
<< CPROVER_PREFIX "deallocated[__CPROVER::constant_infinity_uint];"
93+
<< '\n';
94+
out << CPROVER_PREFIX "bool "
95+
<< CPROVER_PREFIX "dead_object[__CPROVER::constant_infinity_uint];"
96+
<< '\n';
9397
out << "const void *" CPROVER_PREFIX "new_object = 0;" << '\n';
9498
out << "" CPROVER_PREFIX "bool " CPROVER_PREFIX "malloc_is_new_array = 0;"
9599
<< '\n';

src/cpp/library/new.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ inline void __delete(void *ptr)
7171
"delete argument must have offset zero");
7272

7373
// catch double delete
74-
__CPROVER_precondition(ptr==0 || __CPROVER_deallocated!=ptr, "double delete");
74+
__CPROVER_precondition(
75+
ptr == 0 || !__CPROVER_deallocated[__CPROVER_POINTER_OBJECT(ptr)],
76+
"double delete");
7577

7678
// catch people who call delete for objects allocated with new[]
7779
__CPROVER_precondition(
@@ -107,8 +109,9 @@ inline void __delete_array(void *ptr)
107109
"delete argument must have offset zero");
108110

109111
// catch double delete
110-
__CPROVER_precondition(ptr==0 || __CPROVER_deallocated!=ptr,
111-
"double delete");
112+
__CPROVER_precondition(
113+
ptr == 0 || !__CPROVER_deallocated[__CPROVER_POINTER_OBJECT(ptr)],
114+
"double delete");
112115

113116
// catch people who call delete[] for objects allocated with new
114117
__CPROVER_precondition(

src/goto-programs/builtin_functions.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919
#include <util/mathematical_expr.h>
2020
#include <util/mathematical_types.h>
2121
#include <util/pointer_expr.h>
22+
#include <util/pointer_predicates.h>
2223
#include <util/prefix.h>
2324
#include <util/rational.h>
2425
#include <util/rational_tools.h>
@@ -1415,16 +1416,9 @@ void goto_convertt::do_function_call_symbol(
14151416
make_temp_symbol(new_lhs, "alloca", dest, mode);
14161417

14171418
// mark pointer to alloca result as dead
1418-
symbol_exprt dead_object_sym =
1419-
ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
1420-
exprt alloca_result =
1421-
typecast_exprt::conditional_cast(new_lhs, dead_object_sym.type());
1422-
if_exprt rhs{
1423-
side_effect_expr_nondett{bool_typet(), source_location},
1424-
std::move(alloca_result),
1425-
dead_object_sym};
1419+
exprt dead_object_expr = dead_object(new_lhs, ns);
14261420
code_assignt assign{
1427-
std::move(dead_object_sym), std::move(rhs), source_location};
1421+
std::move(dead_object_expr), true_exprt{}, source_location};
14281422
targets.destructor_stack.add(assign);
14291423
}
14301424
else

src/util/pointer_predicates.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,19 @@ exprt deallocated(const exprt &pointer, const namespacet &ns)
4545
// we check __CPROVER_deallocated!
4646
const symbolt &deallocated_symbol=ns.lookup(CPROVER_PREFIX "deallocated");
4747

48-
return same_object(pointer, deallocated_symbol.symbol_expr());
48+
return index_exprt{
49+
deallocated_symbol.symbol_expr(),
50+
typecast_exprt::conditional_cast(pointer_object(pointer), index_type())};
4951
}
5052

5153
exprt dead_object(const exprt &pointer, const namespacet &ns)
5254
{
5355
// we check __CPROVER_dead_object!
5456
const symbolt &deallocated_symbol=ns.lookup(CPROVER_PREFIX "dead_object");
5557

56-
return same_object(pointer, deallocated_symbol.symbol_expr());
58+
return index_exprt{
59+
deallocated_symbol.symbol_expr(),
60+
typecast_exprt::conditional_cast(pointer_object(pointer), index_type())};
5761
}
5862

5963
exprt good_pointer(const exprt &pointer)

0 commit comments

Comments
 (0)