Skip to content

Commit b47a7b2

Browse files
Merge pull request #7313 from thomasspriggs/tas/dynamic_object
Add support for `__CPROVER_DYNAMIC_OBJECT` to incremental SMT decision procedure
2 parents 02d698e + f398ace commit b47a7b2

22 files changed

+374
-37
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
bool nondet_bool();
6+
7+
void main()
8+
{
9+
char local;
10+
void *pointer = &local;
11+
const bool make_dynamic = nondet_bool();
12+
if(make_dynamic)
13+
{
14+
pointer = malloc(1);
15+
}
16+
assert(__CPROVER_DYNAMIC_OBJECT(pointer));
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
assert_dynamic.c
3+
--trace
4+
Passing problem to incremental SMT2 solving
5+
line 16 assertion __CPROVER_DYNAMIC_OBJECT\(pointer\)\: FAILURE
6+
make_dynamic\=FALSE
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
make_dynamic\=TRUE
11+
--
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
bool nondet_bool();
6+
7+
void main()
8+
{
9+
char local;
10+
void *pointer = &local;
11+
const bool make_dynamic = nondet_bool();
12+
if(make_dynamic)
13+
{
14+
pointer = malloc(1);
15+
}
16+
assert(!__CPROVER_DYNAMIC_OBJECT(pointer));
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
assert_not_dynamic.c
3+
--trace
4+
Passing problem to incremental SMT2 solving
5+
line 16 assertion \!__CPROVER_DYNAMIC_OBJECT\(pointer\)\: FAILURE
6+
make_dynamic\=TRUE
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
make_dynamic\=FALSE
11+
--
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <assert.h>
2+
#include <stdbool.h>
3+
#include <stdlib.h>
4+
5+
bool nondet_bool();
6+
7+
void main()
8+
{
9+
char local;
10+
void *pointer = &local;
11+
const bool make_dynamic = nondet_bool();
12+
if(make_dynamic)
13+
{
14+
pointer = malloc(1);
15+
}
16+
assert(make_dynamic || !__CPROVER_DYNAMIC_OBJECT(pointer));
17+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
valid.c
3+
--trace
4+
Passing problem to incremental SMT2 solving
5+
line 16 assertion make_dynamic \|\| \!__CPROVER_DYNAMIC_OBJECT\(pointer\)\: SUCCESS
6+
VERIFICATION SUCCESSFUL
7+
^EXIT=0$
8+
^SIGNAL=0$
9+
--
10+
--

src/solvers/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ SRC = $(BOOLEFORCE_SRC) \
203203
smt2_incremental/convert_expr_to_smt.cpp \
204204
smt2_incremental/object_tracking.cpp \
205205
smt2_incremental/type_size_mapping.cpp \
206+
smt2_incremental/smt_is_dynamic_object.cpp \
206207
smt2_incremental/smt_object_size.cpp \
207208
smt2_incremental/smt_response_validation.cpp \
208209
smt2_incremental/smt_solver_process.cpp \

src/solvers/smt2_incremental/convert_expr_to_smt.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,11 +1042,18 @@ static smt_termt convert_expr_to_smt(
10421042

10431043
static smt_termt convert_expr_to_smt(
10441044
const is_dynamic_object_exprt &is_dynamic_object,
1045-
const sub_expression_mapt &converted)
1045+
const sub_expression_mapt &converted,
1046+
const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
10461047
{
1047-
UNIMPLEMENTED_FEATURE(
1048-
"Generation of SMT formula for is dynamic object expression: " +
1049-
is_dynamic_object.pretty());
1048+
const smt_termt &pointer = converted.at(is_dynamic_object.address());
1049+
const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1050+
INVARIANT(
1051+
pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1052+
const std::size_t pointer_width = pointer_sort->bit_width();
1053+
return apply_is_dynamic_object(
1054+
std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1055+
pointer_width - 1,
1056+
pointer_width - config.bv_encoding.object_bits)(pointer)});
10501057
}
10511058

10521059
static smt_termt convert_expr_to_smt(
@@ -1458,7 +1465,8 @@ static smt_termt dispatch_expr_to_smt_conversion(
14581465
const sub_expression_mapt &converted,
14591466
const smt_object_mapt &object_map,
14601467
const type_size_mapt &pointer_sizes,
1461-
const smt_object_sizet::make_applicationt &call_object_size)
1468+
const smt_object_sizet::make_applicationt &call_object_size,
1469+
const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
14621470
{
14631471
if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
14641472
{
@@ -1660,7 +1668,8 @@ static smt_termt dispatch_expr_to_smt_conversion(
16601668
const auto is_dynamic_object =
16611669
expr_try_dynamic_cast<is_dynamic_object_exprt>(expr))
16621670
{
1663-
return convert_expr_to_smt(*is_dynamic_object, converted);
1671+
return convert_expr_to_smt(
1672+
*is_dynamic_object, converted, apply_is_dynamic_object);
16641673
}
16651674
if(
16661675
const auto is_invalid_pointer =
@@ -1837,7 +1846,8 @@ smt_termt convert_expr_to_smt(
18371846
const exprt &expr,
18381847
const smt_object_mapt &object_map,
18391848
const type_size_mapt &pointer_sizes,
1840-
const smt_object_sizet::make_applicationt &object_size)
1849+
const smt_object_sizet::make_applicationt &object_size,
1850+
const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object)
18411851
{
18421852
#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
18431853
static bool in_conversion = false;
@@ -1856,7 +1866,12 @@ smt_termt convert_expr_to_smt(
18561866
if(find_result != sub_expression_map.cend())
18571867
return;
18581868
smt_termt term = dispatch_expr_to_smt_conversion(
1859-
expr, sub_expression_map, object_map, pointer_sizes, object_size);
1869+
expr,
1870+
sub_expression_map,
1871+
object_map,
1872+
pointer_sizes,
1873+
object_size,
1874+
is_dynamic_object);
18601875
sub_expression_map.emplace_hint(find_result, expr, std::move(term));
18611876
});
18621877
return std::move(sub_expression_map.at(lowered_expr));

src/solvers/smt2_incremental/convert_expr_to_smt.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <solvers/smt2_incremental/ast/smt_sorts.h>
77
#include <solvers/smt2_incremental/ast/smt_terms.h>
88
#include <solvers/smt2_incremental/object_tracking.h>
9+
#include <solvers/smt2_incremental/smt_is_dynamic_object.h>
910
#include <solvers/smt2_incremental/smt_object_size.h>
1011
#include <solvers/smt2_incremental/type_size_mapping.h>
1112

@@ -27,6 +28,7 @@ smt_termt convert_expr_to_smt(
2728
const exprt &expression,
2829
const smt_object_mapt &object_map,
2930
const type_size_mapt &pointer_sizes,
30-
const smt_object_sizet::make_applicationt &object_size);
31+
const smt_object_sizet::make_applicationt &object_size,
32+
const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object);
3133

3234
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_CONVERT_EXPR_TO_SMT_H

src/solvers/smt2_incremental/object_tracking.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <util/arith_tools.h>
66
#include <util/c_types.h>
77
#include <util/pointer_offset_size.h>
8+
#include <util/pointer_predicates.h>
9+
#include <util/prefix.h>
810
#include <util/std_code.h>
911
#include <util/std_expr.h>
1012
#include <util/string_constant.h>
@@ -49,6 +51,7 @@ static decision_procedure_objectt make_null_object()
4951
null_object.unique_id = 0;
5052
null_object.base_expression = null_pointer_exprt{pointer_type(void_type())};
5153
null_object.size = from_integer(0, size_type());
54+
null_object.is_dynamic = false;
5255
return null_object;
5356
}
5457

@@ -60,6 +63,7 @@ static decision_procedure_objectt make_invalid_pointer_object()
6063
invalid_pointer_object.unique_id = 1;
6164
invalid_pointer_object.base_expression = make_invalid_pointer_expr();
6265
invalid_pointer_object.size = from_integer(0, size_type());
66+
invalid_pointer_object.is_dynamic = false;
6367
return invalid_pointer_object;
6468
}
6569

@@ -77,6 +81,23 @@ smt_object_mapt initial_smt_object_map()
7781
return object_map;
7882
}
7983

84+
/// This function returns true for heap allocated objects or false for stack
85+
/// allocated objects.
86+
static bool is_dynamic(const exprt &object)
87+
{
88+
// This check corresponds to the symbols created in
89+
// `goto_symext::symex_allocate`, which implements the `__CPROVER_allocate`
90+
// intrinsic function used by the standard library models.
91+
const bool dynamic_type = object.type().get_bool(ID_C_dynamic);
92+
if(dynamic_type)
93+
return true;
94+
const auto symbol = expr_try_dynamic_cast<symbol_exprt>(object);
95+
bool symbol_is_dynamic =
96+
symbol &&
97+
has_prefix(id2string(symbol->get_identifier()), SYMEX_DYNAMIC_PREFIX);
98+
return symbol_is_dynamic;
99+
}
100+
80101
void track_expression_objects(
81102
const exprt &expression,
82103
const namespacet &ns,
@@ -93,6 +114,7 @@ void track_expression_objects(
93114
object.base_expression = object_base;
94115
object.unique_id = object_map.size();
95116
object.size = *size;
117+
object.is_dynamic = is_dynamic(object_base);
96118
object_map.emplace_hint(find_result, object_base, std::move(object));
97119
});
98120
}

0 commit comments

Comments
 (0)