Skip to content

Commit a99c4ff

Browse files
author
Daniel Kroening
authored
Merge pull request diffblue#2497 from diffblue/simplify_byte_extract_fix
avoid non-termination of simplify_exprt::simplify_byte_extract(array_of(...))
2 parents c7457fb + fc4aab3 commit a99c4ff

File tree

6 files changed

+54
-20
lines changed

6 files changed

+54
-20
lines changed
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
test.class
3+
--function test.check
4+
^VERIFICATION FAILED$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
Checks that a non-termination bug no longer occurs in simplify_byte_extract
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class test {
2+
3+
public static int check()
4+
{
5+
boolean[] assigned = new boolean[3];
6+
if (assigned[0] == false) {
7+
assert false;
8+
}
9+
return 1;
10+
}
11+
}

src/util/simplify_expr.cpp

+27-16
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,7 @@ exprt simplify_exprt::bits2expr(
15931593
return nil_exprt();
15941594
}
15951595

1596-
std::string simplify_exprt::expr2bits(
1596+
optionalt<std::string> simplify_exprt::expr2bits(
15971597
const exprt &expr,
15981598
bool little_endian)
15991599
{
@@ -1630,27 +1630,29 @@ std::string simplify_exprt::expr2bits(
16301630
std::string result;
16311631
forall_operands(it, expr)
16321632
{
1633-
std::string tmp=expr2bits(*it, little_endian);
1634-
if(tmp.empty())
1635-
return tmp; // failed
1636-
result+=tmp;
1633+
auto tmp=expr2bits(*it, little_endian);
1634+
if(!tmp.has_value())
1635+
return {}; // failed
1636+
result+=tmp.value();
16371637
}
1638+
16381639
return result;
16391640
}
16401641
else if(expr.id()==ID_array)
16411642
{
16421643
std::string result;
16431644
forall_operands(it, expr)
16441645
{
1645-
std::string tmp=expr2bits(*it, little_endian);
1646-
if(tmp.empty())
1647-
return tmp; // failed
1648-
result+=tmp;
1646+
auto tmp=expr2bits(*it, little_endian);
1647+
if(!tmp.has_value())
1648+
return {}; // failed
1649+
result+=tmp.value();
16491650
}
1651+
16501652
return result;
16511653
}
16521654

1653-
return "";
1655+
return {};
16541656
}
16551657

16561658
bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
@@ -1734,12 +1736,19 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
17341736
return true;
17351737

17361738
if(expr.op().id()==ID_array_of &&
1737-
expr.op().op0().id()==ID_constant)
1739+
to_array_of_expr(expr.op()).op().id()==ID_constant)
17381740
{
1739-
std::string const_bits=
1740-
expr2bits(expr.op().op0(),
1741+
const auto const_bits_opt=
1742+
expr2bits(to_array_of_expr(expr.op()).op(),
17411743
byte_extract_id()==ID_byte_extract_little_endian);
17421744

1745+
if(!const_bits_opt.has_value())
1746+
return true;
1747+
1748+
std::string const_bits=const_bits_opt.value();
1749+
1750+
DATA_INVARIANT(!const_bits.empty(), "bit representation must be non-empty");
1751+
17431752
// double the string until we have sufficiently many bits
17441753
while(mp_integer(const_bits.size())<offset*8+el_size)
17451754
const_bits+=const_bits;
@@ -1776,15 +1785,17 @@ bool simplify_exprt::simplify_byte_extract(byte_extract_exprt &expr)
17761785
}
17771786

17781787
// extract bits of a constant
1779-
std::string bits=
1788+
const auto bits=
17801789
expr2bits(expr.op(), expr.id()==ID_byte_extract_little_endian);
1790+
17811791
// exact match of length only - otherwise we might lose bits of
17821792
// flexible array members at the end of a struct
1783-
if(mp_integer(bits.size())==el_size+offset*8)
1793+
if(bits.has_value() &&
1794+
mp_integer(bits->size())==el_size+offset*8)
17841795
{
17851796
std::string bits_cut=
17861797
std::string(
1787-
bits,
1798+
bits.value(),
17881799
integer2size_t(offset*8),
17891800
integer2size_t(el_size));
17901801

src/util/simplify_expr_class.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,8 @@ class simplify_exprt
151151
// bit-level conversions
152152
exprt bits2expr(
153153
const std::string &bits, const typet &type, bool little_endian);
154-
std::string expr2bits(const exprt &expr, bool little_endian);
154+
155+
optionalt<std::string> expr2bits(const exprt &, bool little_endian);
155156

156157
protected:
157158
const namespacet &ns;

src/util/simplify_expr_struct.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,12 @@ bool simplify_exprt::simplify_member(exprt &expr)
190190
if(target_size!=-1)
191191
{
192192
mp_integer target_bits=target_size*8;
193-
std::string bits=expr2bits(op, true);
193+
const auto bits=expr2bits(op, true);
194194

195-
if(mp_integer(bits.size())>=target_bits)
195+
if(bits.has_value() &&
196+
mp_integer(bits->size())>=target_bits)
196197
{
197-
std::string bits_cut=std::string(bits, 0, integer2size_t(target_bits));
198+
std::string bits_cut=std::string(*bits, 0, integer2size_t(target_bits));
198199

199200
exprt tmp=bits2expr(bits_cut, expr.type(), true);
200201

0 commit comments

Comments
 (0)