Skip to content

Commit 7d88715

Browse files
authored
Merge pull request #4379 from smowton/smowton/fix/smt2-lower-byte-update-before-find-symbols
SMT2 backend: remove byte operators before calling find_symbols
2 parents 8a7e1b9 + 0411ef8 commit 7d88715

File tree

7 files changed

+118
-34
lines changed

7 files changed

+118
-34
lines changed

regression/cbmc/assigning_nullpointers_should_not_crash_symex/test.desc

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

44
^EXIT=0$

regression/cbmc/byte_update10/main.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <assert.h>
2+
#include <stdio.h>
3+
4+
int main(int argc, char **argv)
5+
{
6+
unsigned long long x[2];
7+
x[0] = 0x0102030405060708;
8+
x[1] = 0x1112131415161718;
9+
10+
unsigned char *alias = (unsigned short *)(((char *)x) + 5);
11+
*alias = 0xed;
12+
13+
unsigned char *alias2 = (unsigned char *)x;
14+
/*
15+
for(int i = 0; i < 16; ++i)
16+
printf("%02hhx\n",alias2[i]);
17+
*/
18+
19+
assert(alias2[0] == 0x08);
20+
assert(alias2[1] == 0x07);
21+
assert(alias2[2] == 0x06);
22+
assert(alias2[3] == 0x05);
23+
assert(alias2[4] == 0x04);
24+
assert(alias2[5] == 0xed);
25+
assert(alias2[6] == 0x02);
26+
assert(alias2[7] == 0x01);
27+
assert(alias2[8] == 0x18);
28+
assert(alias2[9] == 0x17);
29+
assert(alias2[10] == 0x16);
30+
assert(alias2[11] == 0x15);
31+
assert(alias2[12] == 0x14);
32+
assert(alias2[13] == 0x13);
33+
assert(alias2[14] == 0x12);
34+
assert(alias2[15] == 0x11);
35+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
--little-endian
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Note this is identical to test byte_update2, except that the array 'x' has
11+
constant size.

regression/cbmc/gcc_c99-bool-1/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
c99-bool-1.c
33

44
^EXIT=0$

src/solvers/lowering/byte_operators.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
10411041
tmp.type() = max_comp_type;
10421042

10431043
return union_exprt(
1044-
max_comp_name, lower_byte_extract(tmp, ns), union_type);
1044+
max_comp_name, lower_byte_extract(tmp, ns), src.type());
10451045
}
10461046
}
10471047

src/solvers/smt2/smt2_conv.cpp

Lines changed: 67 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include <util/arith_tools.h>
1515
#include <util/c_types.h>
1616
#include <util/config.h>
17+
#include <util/expr_iterator.h>
1718
#include <util/expr_util.h>
1819
#include <util/fixedbv.h>
1920
#include <util/format_expr.h>
@@ -612,24 +613,6 @@ void smt2_convt::convert_address_of_rec(
612613
expr.id_string());
613614
}
614615

615-
void smt2_convt::convert_byte_extract(const byte_extract_exprt &expr)
616-
{
617-
// we just run the flattener
618-
exprt flattened_expr = lower_byte_extract(expr, ns);
619-
unflatten(wheret::BEGIN, expr.type());
620-
convert_expr(flattened_expr);
621-
unflatten(wheret::END, expr.type());
622-
}
623-
624-
void smt2_convt::convert_byte_update(const byte_update_exprt &expr)
625-
{
626-
// we just run the flattener
627-
exprt flattened_expr = lower_byte_update(expr, ns);
628-
unflatten(wheret::BEGIN, expr.type());
629-
convert_expr(flattened_expr);
630-
unflatten(wheret::END, expr.type());
631-
}
632-
633616
literalt smt2_convt::convert(const exprt &expr)
634617
{
635618
PRECONDITION(expr.type().id() == ID_bool);
@@ -647,7 +630,7 @@ literalt smt2_convt::convert(const exprt &expr)
647630

648631
out << "\n";
649632

650-
find_symbols(expr);
633+
exprt prepared_expr = prepare_for_convert_expr(expr);
651634

652635
literalt l(no_boolean_variables, false);
653636
no_boolean_variables++;
@@ -656,7 +639,7 @@ literalt smt2_convt::convert(const exprt &expr)
656639
out << "(define-fun ";
657640
convert_literal(l);
658641
out << " () Bool ";
659-
convert_expr(expr);
642+
convert_expr(prepared_expr);
660643
out << ")" << "\n";
661644

662645
return l;
@@ -1431,12 +1414,14 @@ void smt2_convt::convert_expr(const exprt &expr)
14311414
else if(expr.id()==ID_byte_extract_little_endian ||
14321415
expr.id()==ID_byte_extract_big_endian)
14331416
{
1434-
convert_byte_extract(to_byte_extract_expr(expr));
1417+
INVARIANT(
1418+
false, "byte_extract ops should be lowered in prepare_for_convert_expr");
14351419
}
14361420
else if(expr.id()==ID_byte_update_little_endian ||
14371421
expr.id()==ID_byte_update_big_endian)
14381422
{
1439-
convert_byte_update(to_byte_update_expr(expr));
1423+
INVARIANT(
1424+
false, "byte_update ops should be lowered in prepare_for_convert_expr");
14401425
}
14411426
else if(expr.id()==ID_width)
14421427
{
@@ -4058,7 +4043,7 @@ void smt2_convt::set_to(const exprt &expr, bool value)
40584043

40594044
id.type=equal_expr.lhs().type();
40604045
find_symbols(id.type);
4061-
find_symbols(equal_expr.rhs());
4046+
exprt prepared_rhs = prepare_for_convert_expr(equal_expr.rhs());
40624047

40634048
std::string smt2_identifier=convert_identifier(identifier);
40644049
smt2_identifiers.insert(smt2_identifier);
@@ -4068,38 +4053,91 @@ void smt2_convt::set_to(const exprt &expr, bool value)
40684053

40694054
convert_type(equal_expr.lhs().type());
40704055
out << " ";
4071-
convert_expr(equal_expr.rhs());
4056+
convert_expr(prepared_rhs);
40724057

40734058
out << ")" << "\n";
40744059
return; // done
40754060
}
40764061
}
40774062
}
40784063

4079-
find_symbols(expr);
4064+
exprt prepared_expr = prepare_for_convert_expr(expr);
40804065

4081-
#if 0
4066+
#if 0
40824067
out << "; CONV: "
40834068
<< format(expr) << "\n";
4084-
#endif
4069+
#endif
40854070

40864071
out << "; set_to " << (value?"true":"false") << "\n"
40874072
<< "(assert ";
40884073

40894074
if(!value)
40904075
{
40914076
out << "(not ";
4092-
convert_expr(expr);
4077+
convert_expr(prepared_expr);
40934078
out << ")";
40944079
}
40954080
else
4096-
convert_expr(expr);
4081+
convert_expr(prepared_expr);
40974082

40984083
out << ")" << "\n"; // assert
40994084

41004085
return;
41014086
}
41024087

4088+
/// Lower byte_update and byte_extract operations within \p expr. Return an
4089+
/// equivalent expression that doesn't use byte operators.
4090+
/// Note this replaces operators post-order (compare \ref lower_byte_operators,
4091+
/// which uses a pre-order walk, replacing in child expressions before the
4092+
/// parent). Pre-order replacement currently fails regression tests: see
4093+
/// https://github.com/diffblue/cbmc/issues/4380
4094+
exprt smt2_convt::lower_byte_operators(const exprt &expr)
4095+
{
4096+
exprt lowered_expr = expr;
4097+
4098+
for(auto it = lowered_expr.depth_begin(), itend = lowered_expr.depth_end();
4099+
it != itend;
4100+
++it)
4101+
{
4102+
if(
4103+
it->id() == ID_byte_extract_little_endian ||
4104+
it->id() == ID_byte_extract_big_endian)
4105+
{
4106+
it.mutate() = lower_byte_extract(to_byte_extract_expr(*it), ns);
4107+
}
4108+
else if(
4109+
it->id() == ID_byte_update_little_endian ||
4110+
it->id() == ID_byte_update_big_endian)
4111+
{
4112+
it.mutate() = lower_byte_update(to_byte_update_expr(*it), ns);
4113+
}
4114+
}
4115+
4116+
return lowered_expr;
4117+
}
4118+
4119+
/// Perform steps necessary before an expression is passed to \ref convert_expr
4120+
/// 1. Replace byte operators (byte_extract, _update) with equivalent
4121+
/// expressions
4122+
/// 2. Call find_symbols to create auxiliary symbols, e.g. for array
4123+
/// expressions.
4124+
/// \param expr: expression to prepare
4125+
/// \return equivalent expression suitable for convert_expr.
4126+
exprt smt2_convt::prepare_for_convert_expr(const exprt &expr)
4127+
{
4128+
// First, replace byte operators, because they may introduce new array
4129+
// expressions that must be seen by find_symbols:
4130+
exprt lowered_expr = lower_byte_operators(expr);
4131+
INVARIANT(
4132+
!has_byte_operator(lowered_expr),
4133+
"lower_byte_operators should remove all byte operators");
4134+
4135+
// Now create symbols for all composite expressions present in lowered_expr:
4136+
find_symbols(lowered_expr);
4137+
4138+
return lowered_expr;
4139+
}
4140+
41034141
void smt2_convt::find_symbols(const exprt &expr)
41044142
{
41054143
// recursive call on type

src/solvers/smt2/smt2_conv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ class smt2_convt:public prop_convt
154154
void flatten_array(const exprt &);
155155

156156
// specific expressions go here
157-
void convert_byte_update(const byte_update_exprt &expr);
158-
void convert_byte_extract(const byte_extract_exprt &expr);
159157
void convert_typecast(const typecast_exprt &expr);
160158
void convert_floatbv_typecast(const floatbv_typecast_exprt &expr);
161159
void convert_struct(const struct_exprt &expr);
@@ -182,6 +180,8 @@ class smt2_convt:public prop_convt
182180
std::string convert_identifier(const irep_idt &identifier);
183181

184182
// auxiliary methods
183+
exprt prepare_for_convert_expr(const exprt &expr);
184+
exprt lower_byte_operators(const exprt &expr);
185185
void find_symbols(const exprt &expr);
186186
void find_symbols(const typet &type);
187187
void find_symbols_rec(const typet &type, std::set<irep_idt> &recstack);

0 commit comments

Comments
 (0)