Skip to content

Commit 11186f7

Browse files
committed
SMT2 backend: lower byte operators before find_symbols
Otherwise the lowering can introduce new array expressions, which the SMT2 backend's convert_expr expects to have been pre-converted into auxiliary symbols.
1 parent 8a7e1b9 commit 11186f7

File tree

4 files changed

+110
-29
lines changed

4 files changed

+110
-29
lines changed

regression/cbmc/byte_update10/main.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include <stdio.h>
2+
#include <assert.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+
36+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
--little-endian
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/solvers/smt2/smt2_conv.cpp

Lines changed: 64 additions & 27 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_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,12 @@ 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(false, "byte_extract ops should be lowered in prepare_expr");
14351418
}
14361419
else if(expr.id()==ID_byte_update_little_endian ||
14371420
expr.id()==ID_byte_update_big_endian)
14381421
{
1439-
convert_byte_update(to_byte_update_expr(expr));
1422+
INVARIANT(false, "byte_update ops should be lowered in prepare_expr");
14401423
}
14411424
else if(expr.id()==ID_width)
14421425
{
@@ -4058,7 +4041,7 @@ void smt2_convt::set_to(const exprt &expr, bool value)
40584041

40594042
id.type=equal_expr.lhs().type();
40604043
find_symbols(id.type);
4061-
find_symbols(equal_expr.rhs());
4044+
exprt prepared_rhs = prepare_expr(equal_expr.rhs());
40624045

40634046
std::string smt2_identifier=convert_identifier(identifier);
40644047
smt2_identifiers.insert(smt2_identifier);
@@ -4068,15 +4051,15 @@ void smt2_convt::set_to(const exprt &expr, bool value)
40684051

40694052
convert_type(equal_expr.lhs().type());
40704053
out << " ";
4071-
convert_expr(equal_expr.rhs());
4054+
convert_expr(prepared_rhs);
40724055

40734056
out << ")" << "\n";
40744057
return; // done
40754058
}
40764059
}
40774060
}
40784061

4079-
find_symbols(expr);
4062+
exprt prepared_expr = prepare_expr(expr);
40804063

40814064
#if 0
40824065
out << "; CONV: "
@@ -4089,17 +4072,71 @@ void smt2_convt::set_to(const exprt &expr, bool value)
40894072
if(!value)
40904073
{
40914074
out << "(not ";
4092-
convert_expr(expr);
4075+
convert_expr(prepared_expr);
40934076
out << ")";
40944077
}
40954078
else
4096-
convert_expr(expr);
4079+
convert_expr(prepared_expr);
40974080

40984081
out << ")" << "\n"; // assert
40994082

41004083
return;
41014084
}
41024085

4086+
exprt smt2_convt::lower_byte_operators_rec(const exprt &expr)
4087+
{
4088+
exprt lowered_expr = expr;
4089+
4090+
for(auto it = lowered_expr.depth_begin(), itend = lowered_expr.depth_end();
4091+
it != itend;
4092+
/* No ++it */)
4093+
{
4094+
if(
4095+
it->id() == ID_byte_extract_little_endian ||
4096+
it->id() == ID_byte_extract_big_endian)
4097+
{
4098+
// Note we must recurse to get a fresh iterator because depth_iteratort
4099+
// currently crashes if we try to recurse into an expression we've
4100+
// altered.
4101+
it.mutate() =
4102+
lower_byte_operators_rec(
4103+
lower_byte_extract(to_byte_extract_expr(*it), ns));
4104+
it.next_sibling_or_parent();
4105+
}
4106+
else if(
4107+
it->id() == ID_byte_update_little_endian ||
4108+
it->id() == ID_byte_update_big_endian)
4109+
{
4110+
// Note we must recurse to get a fresh iterator because depth_iteratort
4111+
// currently crashes if we try to recurse into an expression we've
4112+
// altered.
4113+
it.mutate() =
4114+
lower_byte_operators_rec(
4115+
lower_byte_update(to_byte_update_expr(*it), ns));
4116+
it.next_sibling_or_parent();
4117+
}
4118+
else
4119+
{
4120+
++it;
4121+
}
4122+
}
4123+
4124+
return lowered_expr;
4125+
}
4126+
4127+
exprt smt2_convt::prepare_expr(const exprt &expr)
4128+
{
4129+
// First, replace byte operators, because they may introduce new array
4130+
// expressions that must be seen by find_symbols:
4131+
exprt lowered_expr = lower_byte_operators_rec(expr);
4132+
INVARIANT(!has_byte_operator(lowered_expr), "should be gone");
4133+
4134+
// Now create symbols for all composite expressions present in lowered_expr:
4135+
find_symbols(lowered_expr);
4136+
4137+
return lowered_expr;
4138+
}
4139+
41034140
void smt2_convt::find_symbols(const exprt &expr)
41044141
{
41054142
// 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_expr(const exprt &expr);
184+
exprt lower_byte_operators_rec(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)