-
Notifications
You must be signed in to change notification settings - Fork 274
Add support for __CPROVER_DYNAMIC_OBJECT
to incremental SMT decision procedure
#7313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9e2f74a
5e29858
1deb0ca
49a5eae
e35a5a6
4d7381e
f398ace
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <assert.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
|
||
bool nondet_bool(); | ||
|
||
void main() | ||
{ | ||
char local; | ||
void *pointer = &local; | ||
const bool make_dynamic = nondet_bool(); | ||
if(make_dynamic) | ||
{ | ||
pointer = malloc(1); | ||
} | ||
assert(__CPROVER_DYNAMIC_OBJECT(pointer)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
CORE | ||
assert_dynamic.c | ||
--trace | ||
Passing problem to incremental SMT2 solving | ||
line 16 assertion __CPROVER_DYNAMIC_OBJECT\(pointer\)\: FAILURE | ||
make_dynamic\=FALSE | ||
^EXIT=10$ | ||
^SIGNAL=0$ | ||
-- | ||
make_dynamic\=TRUE | ||
-- |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <assert.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
|
||
bool nondet_bool(); | ||
|
||
void main() | ||
{ | ||
char local; | ||
void *pointer = &local; | ||
const bool make_dynamic = nondet_bool(); | ||
if(make_dynamic) | ||
{ | ||
pointer = malloc(1); | ||
} | ||
assert(!__CPROVER_DYNAMIC_OBJECT(pointer)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
CORE | ||
assert_not_dynamic.c | ||
--trace | ||
Passing problem to incremental SMT2 solving | ||
line 16 assertion \!__CPROVER_DYNAMIC_OBJECT\(pointer\)\: FAILURE | ||
make_dynamic\=TRUE | ||
^EXIT=10$ | ||
^SIGNAL=0$ | ||
-- | ||
make_dynamic\=FALSE | ||
-- |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include <assert.h> | ||
#include <stdbool.h> | ||
#include <stdlib.h> | ||
|
||
bool nondet_bool(); | ||
|
||
void main() | ||
{ | ||
char local; | ||
void *pointer = &local; | ||
const bool make_dynamic = nondet_bool(); | ||
if(make_dynamic) | ||
{ | ||
pointer = malloc(1); | ||
} | ||
assert(make_dynamic || !__CPROVER_DYNAMIC_OBJECT(pointer)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
CORE | ||
valid.c | ||
--trace | ||
Passing problem to incremental SMT2 solving | ||
line 16 assertion make_dynamic \|\| \!__CPROVER_DYNAMIC_OBJECT\(pointer\)\: SUCCESS | ||
VERIFICATION SUCCESSFUL | ||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
-- | ||
-- |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -255,6 +255,7 @@ smt2_incremental_decision_proceduret::smt2_incremental_decision_proceduret( | |
smt_set_option_commandt{smt_option_produce_modelst{true}}); | ||
solver_process->send(smt_set_logic_commandt{smt_logic_allt{}}); | ||
solver_process->send(object_size_function.declaration); | ||
solver_process->send(is_dynamic_object_function.declaration); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏️ Personal opinion: I know |
||
} | ||
|
||
void smt2_incremental_decision_proceduret::ensure_handle_for_expr_defined( | ||
|
@@ -321,12 +322,14 @@ smt2_incremental_decision_proceduret::convert_expr_to_smt(const exprt &expr) | |
ns, | ||
pointer_sizes_map, | ||
object_map, | ||
object_size_function.make_application); | ||
object_size_function.make_application, | ||
is_dynamic_object_function.make_application); | ||
return ::convert_expr_to_smt( | ||
substituted, | ||
object_map, | ||
pointer_sizes_map, | ||
object_size_function.make_application); | ||
object_size_function.make_application, | ||
is_dynamic_object_function.make_application); | ||
} | ||
|
||
exprt smt2_incremental_decision_proceduret::handle(const exprt &expr) | ||
|
@@ -376,7 +379,8 @@ array_exprt smt2_incremental_decision_proceduret::get_expr( | |
from_integer(index, index_type), | ||
object_map, | ||
pointer_sizes_map, | ||
object_size_function.make_application)), | ||
object_size_function.make_application, | ||
is_dynamic_object_function.make_application)), | ||
type.element_type())); | ||
} | ||
return array_exprt{elements, type}; | ||
|
@@ -442,7 +446,8 @@ exprt smt2_incremental_decision_proceduret::get(const exprt &expr) const | |
expr, | ||
object_map, | ||
pointer_sizes_map, | ||
object_size_function.make_application); | ||
object_size_function.make_application, | ||
is_dynamic_object_function.make_application); | ||
} | ||
else | ||
{ | ||
|
@@ -548,26 +553,28 @@ static decision_proceduret::resultt lookup_decision_procedure_result( | |
UNREACHABLE; | ||
} | ||
|
||
void smt2_incremental_decision_proceduret::define_object_sizes() | ||
void smt2_incremental_decision_proceduret::define_object_properties() | ||
{ | ||
object_size_defined.resize(object_map.size()); | ||
object_properties_defined.resize(object_map.size()); | ||
for(const auto &key_value : object_map) | ||
{ | ||
const decision_procedure_objectt &object = key_value.second; | ||
if(object_size_defined[object.unique_id]) | ||
if(object_properties_defined[object.unique_id]) | ||
continue; | ||
else | ||
object_size_defined[object.unique_id] = true; | ||
object_properties_defined[object.unique_id] = true; | ||
define_dependent_functions(object.size); | ||
solver_process->send(object_size_function.make_definition( | ||
object.unique_id, convert_expr_to_smt(object.size))); | ||
solver_process->send(is_dynamic_object_function.make_definition( | ||
object.unique_id, object.is_dynamic)); | ||
} | ||
} | ||
|
||
decision_proceduret::resultt smt2_incremental_decision_proceduret::dec_solve() | ||
{ | ||
++number_of_solver_calls; | ||
define_object_sizes(); | ||
define_object_properties(); | ||
const smt_responset result = get_response_to_command( | ||
*solver_process, smt_check_sat_commandt{}, identifier_table); | ||
if(const auto check_sat_response = result.cast<smt_check_sat_responset>()) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ | |
|
||
#include <solvers/smt2_incremental/ast/smt_terms.h> | ||
#include <solvers/smt2_incremental/object_tracking.h> | ||
#include <solvers/smt2_incremental/smt_is_dynamic_object.h> | ||
#include <solvers/smt2_incremental/smt_object_size.h> | ||
#include <solvers/smt2_incremental/type_size_mapping.h> | ||
#include <solvers/stack_decision_procedure.h> | ||
|
@@ -92,8 +93,9 @@ class smt2_incremental_decision_proceduret final | |
/// \note This function is non-const because it mutates the object_map. | ||
smt_termt convert_expr_to_smt(const exprt &expr); | ||
void define_index_identifiers(const exprt &expr); | ||
/// Sends the solver the definitions of the object sizes. | ||
void define_object_sizes(); | ||
/// Sends the solver the definitions of the object sizes and dynamic memory | ||
/// statuses. | ||
void define_object_properties(); | ||
|
||
/// Namespace for looking up the expressions which symbol_exprts relate to. | ||
/// This includes the symbols defined outside of the decision procedure but | ||
|
@@ -149,16 +151,21 @@ class smt2_incremental_decision_proceduret final | |
/// This map is used to track object related state. See documentation in | ||
/// object_tracking.h for details. | ||
smt_object_mapt object_map; | ||
/// The size of each object is separately defined as a pre-solving step. | ||
/// `object_size_defined[object ID]` is set to true for objects where the size | ||
/// has been defined. This is used to avoid defining the size of the same | ||
/// object multiple times in the case where multiple rounds of solving are | ||
/// carried out. | ||
std::vector<bool> object_size_defined; | ||
/// The size of each object and the dynamic object stus is separately defined | ||
/// as a pre-solving step. `object_properties_defined[object ID]` is set to | ||
/// true for objects where the size has been defined. This is used to avoid | ||
/// defining the size of the same object multiple times in the case where | ||
/// multiple rounds of solving are carried out. | ||
std::vector<bool> object_properties_defined; | ||
/// Implementation of the SMT formula for the object size function. This is | ||
/// stateful because it depends on the configuration of the number of object | ||
/// bits and how many bits wide the size type is configured to be. | ||
smt_object_sizet object_size_function; | ||
/// Implementation of the SMT formula for the dynamic object status lookup | ||
/// function. This is stateful because it depends on the configuration of the | ||
/// number of object bits and how many bits wide the size type is configured | ||
/// to be. | ||
smt_is_dynamic_objectt is_dynamic_object_function; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⛏️ Add documentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added. |
||
/// Precalculated type sizes used for pointer arithmetic. | ||
type_size_mapt pointer_sizes_map; | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ As we have a test checking that the object is not dynamic, should we avoid the nondeterministic boolean so that one verification leads to
FAILURE
and one toSUCCESS
?Otherwise we never check for
SUCCESS
(UNSAT
on the SMT level).