Skip to content

Commit decd283

Browse files
author
Enrico Steffinlongo
authored
Merge pull request #7868 from NlightNFotis/shadow_mem_rev
Shadow Memory: Refactoring, enabling tests and minor doxygen improvements.
2 parents d927b47 + 7417bef commit decd283

File tree

17 files changed

+142
-31
lines changed

17 files changed

+142
-31
lines changed

regression/cbmc-shadow-memory/char1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/constchar-pointers1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--unwind 11
44
^EXIT=0$

regression/cbmc-shadow-memory/linked-list1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/linked-list2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/maybe-null1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/nondet-size-arrays1/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include <assert.h>
22
#include <stdlib.h>
33

4+
#ifdef _WIN32
5+
void *alloca(size_t alloca_size);
6+
#endif
7+
48
int main()
59
{
610
__CPROVER_field_decl_local("field1", (char)0);

regression/cbmc-shadow-memory/nondet-size-arrays1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/struct-set1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/taint-example1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33
--unwind 15
44
^EXIT=0$

regression/cbmc-shadow-memory/union-get-max1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/union-get-or1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

regression/cbmc-shadow-memory/union-set1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
main.c
33

44
^EXIT=0$

src/goto-symex/shadow_memory_util.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@ Author: Peter Schrammel
2222
#include <util/ssa_expr.h>
2323
#include <util/std_expr.h>
2424

25-
#include <langapi/language_util.h> // IWYU pragma: keep
2625

2726
// TODO: change DEBUG_SM to DEBUG_SHADOW_MEMORY (it also appears in other files)
2827

2928
irep_idt extract_field_name(const exprt &string_expr)
3029
{
31-
if(string_expr.id() == ID_typecast)
30+
if(can_cast_expr<typecast_exprt>(string_expr))
3231
return extract_field_name(to_typecast_expr(string_expr).op());
33-
else if(string_expr.id() == ID_address_of)
32+
else if(can_cast_expr<address_of_exprt>(string_expr))
3433
return extract_field_name(to_address_of_expr(string_expr).object());
35-
else if(string_expr.id() == ID_index)
34+
else if(can_cast_expr<index_exprt>(string_expr))
3635
return extract_field_name(to_index_expr(string_expr).array());
3736
else if(string_expr.id() == ID_string_constant)
3837
{
@@ -42,8 +41,8 @@ irep_idt extract_field_name(const exprt &string_expr)
4241
UNREACHABLE;
4342
}
4443

45-
/// If the given type is an array type, then remove the L2 level
46-
/// renaming from its size.
44+
/// If the given type is an array type, then remove the L2 level renaming
45+
/// from its size.
4746
/// \param type Type to be modified
4847
static void remove_array_type_l2(typet &type)
4948
{
@@ -56,7 +55,7 @@ static void remove_array_type_l2(typet &type)
5655

5756
exprt deref_expr(const exprt &expr)
5857
{
59-
if(expr.id() == ID_address_of)
58+
if(can_cast_expr<address_of_exprt>(expr))
6059
{
6160
return to_address_of_expr(expr).object();
6261
}
@@ -67,7 +66,7 @@ exprt deref_expr(const exprt &expr)
6766
void clean_pointer_expr(exprt &expr, const typet &type)
6867
{
6968
if(
70-
type.id() == ID_array && expr.id() == ID_symbol &&
69+
can_cast_type<array_typet>(type) && can_cast_expr<symbol_exprt>(expr) &&
7170
to_array_type(type).size().get_bool(ID_C_SSA_symbol))
7271
{
7372
remove_array_type_l2(expr.type());
@@ -80,15 +79,15 @@ void clean_pointer_expr(exprt &expr, const typet &type)
8079
expr = address_of_exprt(expr);
8180
expr.type() = pointer_type(char_type());
8281
}
83-
else if(expr.id() == ID_dereference)
82+
else if(can_cast_expr<dereference_exprt>(expr))
8483
{
8584
expr = to_dereference_expr(expr).pointer();
8685
}
8786
else
8887
{
8988
expr = address_of_exprt(expr);
9089
}
91-
POSTCONDITION(expr.type().id() == ID_pointer);
90+
POSTCONDITION(can_cast_type<pointer_typet>(expr.type()));
9291
}
9392

9493
void log_set_field(
@@ -691,7 +690,16 @@ static exprt get_matched_expr_cond(
691690
return expr_cond;
692691
}
693692

694-
// TODO: doxygen?
693+
/// Retrieve the shadow value a pointer expression may point to.
694+
/// \param shadow The shadow expression.
695+
/// \param matched_base_descriptor The base descriptor for the shadow object.
696+
/// \param expr The pointer expression.
697+
/// \param ns The namespace within which we're going to perform symbol lookups.
698+
/// \param log The message log to which we're going to print debugging messages,
699+
/// if debugging is set.
700+
/// \returns A `valuet` object denoting the dereferenced object within shadow
701+
/// memory, guarded by a appropriate condition (of the form
702+
/// pointer == &shadow_object).
695703
static value_set_dereferencet::valuet get_shadow_dereference(
696704
const exprt &shadow,
697705
const object_descriptor_exprt &matched_base_descriptor,

src/goto-symex/shadow_memory_util.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,34 @@ irep_idt extract_field_name(const exprt &string_expr);
3737
/// \param type The followed type of expr.
3838
void clean_pointer_expr(exprt &expr, const typet &type);
3939

40-
// TODO: Daxygen
40+
/// Converts a given expression into a dereference_exprt.
4141
exprt deref_expr(const exprt &expr);
4242

43-
// TODO: DOxYGEN
43+
/// Logs setting a value to a given shadow field. Mainly for use for
44+
/// debugging purposes.
4445
void log_set_field(
4546
const namespacet &ns,
4647
const messaget &log,
4748
const irep_idt &field_name,
4849
const exprt &expr,
4950
const exprt &value);
5051

51-
// TODO: doxygen
52+
/// Logs setting a value to a given shadow field. Mainly for use for
53+
/// debugging purposes.
5254
void log_get_field(
5355
const namespacet &ns,
5456
const messaget &log,
5557
const irep_idt &field_name,
5658
const exprt &expr);
5759

58-
// TODO: doxygen
60+
/// Logs the retrieval of the value associated with a given shadow
61+
/// memory field. Mainly for use for debugging purposes. Dual to log_get_field.
5962
void log_value_set(
6063
const namespacet &ns,
6164
const messaget &log,
6265
const std::vector<exprt> &value_set);
6366

64-
// TODO: doxygen
67+
/// Log a match between a value in the value set of a given expression, and
6568
void log_value_set_match(
6669
const namespacet &ns,
6770
const messaget &log,

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Author: Daniel Kroening, [email protected]
1717

1818
#include <util/arith_tools.h>
1919
#include <util/byte_operators.h>
20+
#include <util/c_types.h>
2021
#include <util/config.h>
2122
#include <util/cprover_prefix.h>
2223
#include <util/expr_iterator.h>
@@ -661,8 +662,21 @@ value_set_dereferencet::valuet value_set_dereferencet::build_reference_to(
661662
result.pointer = typecast_exprt::conditional_cast(
662663
address_of_exprt{skip_typecast(o.root_object())}, pointer_type);
663664

664-
if(!memory_model(result.value, dereference_type, offset, ns))
665+
if(memory_model(result.value, dereference_type, offset, ns))
666+
{
667+
// set pointer correctly
668+
result.pointer = typecast_exprt::conditional_cast(
669+
plus_exprt(
670+
typecast_exprt(
671+
result.pointer,
672+
pointer_typet(char_type(), pointer_type.get_width())),
673+
offset),
674+
pointer_type);
675+
}
676+
else
677+
{
665678
return {}; // give up, no way that this is ok
679+
}
666680

667681
return result;
668682
}

src/util/expr_initializer.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Author: Daniel Kroening, [email protected]
1818
#include "magic.h"
1919
#include "namespace.h" // IWYU pragma: keep
2020
#include "std_code.h"
21+
#include "symbol_table.h"
2122

2223
class expr_initializert
2324
{
@@ -393,9 +394,15 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
393394

394395
// We haven't got a constant. So, build the expression using shift-and-or.
395396
exprt::operandst values;
397+
398+
typet operation_type = output_type;
399+
if(const auto ptr_type = type_try_dynamic_cast<pointer_typet>(output_type))
400+
{
401+
operation_type = unsignedbv_typet{ptr_type->get_width()};
402+
}
396403
// Let's cast init_byte_expr to output_type.
397404
const exprt casted_init_byte_expr =
398-
typecast_exprt::conditional_cast(init_byte_expr, output_type);
405+
typecast_exprt::conditional_cast(init_byte_expr, operation_type);
399406
values.push_back(casted_init_byte_expr);
400407
for(size_t i = 1; i < size; ++i)
401408
{
@@ -404,8 +411,9 @@ exprt duplicate_per_byte(const exprt &init_byte_expr, const typet &output_type)
404411
from_integer(config.ansi_c.char_width * i, size_type())));
405412
}
406413
if(values.size() == 1)
407-
return values[0];
408-
return multi_ary_exprt(ID_bitor, values, output_type);
414+
return typecast_exprt::conditional_cast(values[0], output_type);
415+
return typecast_exprt::conditional_cast(
416+
multi_ary_exprt(ID_bitor, values, operation_type), output_type);
409417
}
410418

411419
// Anything else. We don't know what to do with it. So, just cast.

unit/util/expr_initializer.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,18 @@ TEST_CASE(
177177
from_integer(init_expr_value, signedbv_typet{init_expr_size}),
178178
output_type);
179179
REQUIRE(result_with_signed_init_type == result);
180+
181+
// Check that replicating a pointer_value is same as unsigned_bv.
182+
const pointer_typet pointer_type{bool_typet{}, output_size};
183+
const auto result_with_pointer_type = duplicate_per_byte(
184+
from_integer(init_expr_value, signedbv_typet{init_expr_size}),
185+
pointer_type);
186+
auto pointer_typed_expected =
187+
from_integer(output_expected_value, unsignedbv_typet{output_size});
188+
// Forcing the type to be pointer_typet otherwise from_integer fails when
189+
// the init value is not 0 (NULL).
190+
pointer_typed_expected.type() = pointer_type;
191+
REQUIRE(result_with_pointer_type == pointer_typed_expected);
180192
}
181193
}
182194

@@ -212,6 +224,21 @@ TEST_CASE(
212224
replicate_expression(casted_init_expr, output_type, replication_count);
213225

214226
REQUIRE(result == expected);
227+
228+
// Check that replicating a pointer_value is same as unsigned_bv modulo a
229+
// typecast outside.
230+
const pointer_typet pointer_type{bool_typet{}, output_size};
231+
const auto pointer_typed_result =
232+
duplicate_per_byte(init_expr, pointer_type);
233+
const auto pointer_unsigned_corr_type = unsignedbv_typet{output_size};
234+
const auto pointer_init_expr =
235+
typecast_exprt::conditional_cast(init_expr, pointer_unsigned_corr_type);
236+
const auto pointer_expected = typecast_exprt::conditional_cast(
237+
replicate_expression(
238+
pointer_init_expr, pointer_unsigned_corr_type, replication_count),
239+
pointer_type);
240+
241+
REQUIRE(pointer_typed_result == pointer_expected);
215242
}
216243
}
217244

@@ -312,6 +339,53 @@ TEST_CASE(
312339
}
313340
}
314341

342+
TEST_CASE(
343+
"expr_initializer on variable-bit pointer type",
344+
"[core][util][expr_initializer]")
345+
{
346+
auto test = expr_initializer_test_environmentt::make();
347+
const std::size_t input_type_size = GENERATE(3, 8, 16, 20);
348+
SECTION(
349+
"Testing with expected type as unsigned_bv of size " +
350+
std::to_string(input_type_size))
351+
{
352+
typet input_type = pointer_typet{bool_typet{}, input_type_size};
353+
SECTION("nondet_initializer works")
354+
{
355+
const auto result = nondet_initializer(input_type, test.loc, test.ns);
356+
REQUIRE(result.has_value());
357+
const auto expected = side_effect_expr_nondett{
358+
pointer_typet{bool_typet{}, input_type_size}, test.loc};
359+
REQUIRE(result.value() == expected);
360+
const auto expr_result =
361+
expr_initializer(input_type, test.loc, test.ns, exprt(ID_nondet));
362+
REQUIRE(expr_result == result);
363+
}
364+
SECTION("zero_initializer works")
365+
{
366+
const auto result = zero_initializer(input_type, test.loc, test.ns);
367+
REQUIRE(result.has_value());
368+
auto expected =
369+
from_integer(0, pointer_typet{bool_typet{}, input_type_size});
370+
REQUIRE(result.value() == expected);
371+
const auto expr_result = expr_initializer(
372+
input_type, test.loc, test.ns, constant_exprt(ID_0, char_type()));
373+
REQUIRE(expr_result == result);
374+
}
375+
SECTION("expr_initializer calls duplicate_per_byte")
376+
{
377+
const exprt init_value =
378+
from_integer(0x0A, unsignedbv_typet{config.ansi_c.char_width});
379+
const auto result =
380+
expr_initializer(input_type, test.loc, test.ns, init_value);
381+
REQUIRE(result.has_value());
382+
const auto expected = duplicate_per_byte(
383+
init_value, pointer_typet{bool_typet{}, input_type_size});
384+
REQUIRE(result.value() == expected);
385+
}
386+
}
387+
}
388+
315389
TEST_CASE(
316390
"expr_initializer on c_enum and c_enum_tag",
317391
"[core][util][expr_initializer]")

0 commit comments

Comments
 (0)