Skip to content
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

Add shadow memory set_field operation #7846

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/char1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/constchar-param1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c
--unwind 11
^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c
--unwind 11
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/errno1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/float1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/getenv1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/global1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/linked-list1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/linked-list2/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/local1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/malloc1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/maybe-null1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/memcpy1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/param1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/static1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/strdup1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c
--unwind 4
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/struct-get-max1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/struct-get-or1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/struct-set1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
56 changes: 56 additions & 0 deletions regression/cbmc-shadow-memory/struct-set2/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <assert.h>

struct S
{
short x[3];
char c;
};

int main(void)
{
__CPROVER_field_decl_local("f", (char)0);

struct S s;

// Setting the struct recursively set all its fields
__CPROVER_set_field(&s, "f", 1);

assert(__CPROVER_get_field(&s.x[0], "f") == 1);
assert(__CPROVER_get_field(&s.x[1], "f") == 1);
assert(__CPROVER_get_field(&s.x[2], "f") == 1);
assert(__CPROVER_get_field(&s.c, "f") == 1);
assert(__CPROVER_get_field(&s, "f") == 1);

// Setting the struct recursively set all its fields
__CPROVER_set_field(&s, "f", 0);

assert(__CPROVER_get_field(&s.x[0], "f") == 0);
assert(__CPROVER_get_field(&s.x[1], "f") == 0);
assert(__CPROVER_get_field(&s.x[2], "f") == 0);
assert(__CPROVER_get_field(&s.c, "f") == 0);
assert(__CPROVER_get_field(&s, "f") == 0);

// Setting a field of the struct changes its values ad after aggregation the whole struct value
__CPROVER_set_field(&s.x[1], "f", 2);

assert(__CPROVER_get_field(&s.x[0], "f") == 0);
assert(__CPROVER_get_field(&s.x[1], "f") == 2);
assert(__CPROVER_get_field(&s.x[2], "f") == 0);
assert(__CPROVER_get_field(&s.c, "f") == 0);
assert(__CPROVER_get_field(&s, "f") == 2);

// Rest shadow memory
__CPROVER_set_field(&s, "f", 0);

// Changing ONLY first cell of S array at field x by using offset with pointer arithmetics
short *p = ((short *)&s) + 1;
__CPROVER_set_field(p, "f", 3);

assert(__CPROVER_get_field(&s.x[0], "f") == 0);
assert(__CPROVER_get_field(&s.x[1], "f") == 3);
assert(__CPROVER_get_field(&s.x[2], "f") == 0);
assert(__CPROVER_get_field(&s.c, "f") == 0);
assert(__CPROVER_get_field(&s, "f") == 3);

return 0;
}
8 changes: 8 additions & 0 deletions regression/cbmc-shadow-memory/struct-set2/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.c

^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
^warning: ignoring
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/taint-example1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c
--unwind 15
^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/trace1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c
--stop-on-fail --unwind 5
^EXIT=10$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/union-get-max1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/union-get-or1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/union-set1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/var-assign1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
KNOWNBUG
main.c

^EXIT=0$
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=6$
Expand Down
2 changes: 1 addition & 1 deletion regression/cbmc-shadow-memory/void-ptr-param2/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FUTURE
CORE
main.c

^EXIT=0$
Expand Down
93 changes: 92 additions & 1 deletion src/goto-symex/shadow_memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,98 @@
goto_symex_statet &state,
const exprt::operandst &arguments)
{
// To be implemented
// parse set_field call
INVARIANT(
arguments.size() == 3, CPROVER_PREFIX "set_field requires 3 arguments");
irep_idt field_name = extract_field_name(arguments[1]);

exprt expr = arguments[0];
typet expr_type = expr.type();
DATA_INVARIANT_WITH_DIAGNOSTICS(
expr_type.id() == ID_pointer,
"shadow memory requires a pointer expression",
irep_pretty_diagnosticst{expr_type});

exprt value = arguments[2];
log_set_field(ns, log, field_name, expr, value);
INVARIANT(
state.shadow_memory.address_fields.count(field_name) == 1,
id2string(field_name) + " should exist");
const auto &addresses = state.shadow_memory.address_fields.at(field_name);

// get value set
replace_invalid_object_by_null(expr);
#ifdef DEBUG_SM
log_set_field(ns, log, field_name, expr, value);
#endif
std::vector<exprt> value_set = state.value_set.get_value_set(expr, ns);
log_value_set(ns, log, value_set);
if(set_field_check_null(ns, log, value_set, expr))
{
log.warning() << "Shadow memory: cannot set shadow memory of NULL"
<< messaget::eom;
return;

Check warning on line 123 in src/goto-symex/shadow_memory.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-symex/shadow_memory.cpp#L121-L123

Added lines #L121 - L123 were not covered by tests
}

// build lhs
const exprt &rhs = value;
size_t mux_size = 0;
optionalt<exprt> maybe_lhs =
get_shadow_memory(expr, value_set, addresses, ns, log, mux_size);

// add to equation
if(maybe_lhs.has_value())
{
if(mux_size >= 10)
{
log.warning() << "Shadow memory: mux size set_field: " << mux_size
<< messaget::eom;

Check warning on line 138 in src/goto-symex/shadow_memory.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-symex/shadow_memory.cpp#L137-L138

Added lines #L137 - L138 were not covered by tests
}
else
{
log.debug() << "Shadow memory: mux size set_field: " << mux_size
<< messaget::eom;
}
const exprt lhs = deref_expr(*maybe_lhs);
#ifdef DEBUG_SM
log.debug() << "Shadow memory: LHS: " << format(lhs) << messaget::eom;
#endif
if(lhs.type().id() == ID_empty)
{
std::stringstream s;
s << "Shadow memory: cannot set shadow memory via type void* for "
<< format(expr)
<< ". Insert a cast to the type that you want to access.";
throw invalid_input_exceptiont(s.str());
}

// Get the type of the shadow memory for this field
const typet &sm_field_type = get_field_init_type(field_name, state);
// Add a conditional cast to the shadow memory field type if `rhs` is not of
// the expected type
const exprt casted_rhs =
typecast_exprt::conditional_cast(rhs, sm_field_type);
// We replicate the rhs value on each byte of the value that we set.
// This allows the get_field or/max semantics to operate correctly
// on unions.
const auto per_byte_rhs =
expr_initializer(lhs.type(), expr.source_location(), ns, casted_rhs);
CHECK_RETURN(per_byte_rhs.has_value());

#ifdef DEBUG_SM
log.debug() << "Shadow memory: RHS: " << format(per_byte_rhs.value())
<< messaget::eom;
#endif
symex_assign(
state,
lhs,
typecast_exprt::conditional_cast(per_byte_rhs.value(), lhs.type()));
}
else
{
log.warning() << "Shadow memory: cannot set_field for " << format(expr)
<< messaget::eom;

Check warning on line 183 in src/goto-symex/shadow_memory.cpp

View check run for this annotation

Codecov / codecov/patch

src/goto-symex/shadow_memory.cpp#L182-L183

Added lines #L182 - L183 were not covered by tests
}
}

// Function synopsis
Expand Down
Loading
Loading