Skip to content

Commit da4866c

Browse files
committed
Use byte-operator lowering when type to be extract is of non-const size
The test included made apparent that we weren't yet handling unbounded byte extracts (out of a bounded object) in flattening.
1 parent dfdd25f commit da4866c

File tree

5 files changed

+67
-6
lines changed

5 files changed

+67
-6
lines changed

regression/cbmc/union17/main.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
int main()
2+
{
3+
// create a union type of non-constant, non-zero size
4+
unsigned x;
5+
__CPROVER_assume(x > 0);
6+
union U
7+
{
8+
unsigned A[x];
9+
};
10+
// create an integer of arbitrary value
11+
int i, i_before;
12+
i_before = i;
13+
// initialize a union of non-zero size from the integer
14+
union U u = *((union U *)&i);
15+
// reading back an integer out of the union should yield the same value for
16+
// the integer as it had before
17+
i = u.A[0];
18+
__CPROVER_assert(i == i_before, "going through union works");
19+
}

regression/cbmc/union17/test.desc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Value sets did not properly track pointers through unions. Thus derferencing
11+
yields __CPROVER_memory, which results in a spurious verification failure.

src/solvers/flattening/boolbv.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,31 @@ void boolbvt::set_to(const exprt &expr, bool value)
517517

518518
bool boolbvt::is_unbounded_array(const typet &type) const
519519
{
520-
if(type.id()!=ID_array)
520+
if(type.id() == ID_struct_tag)
521+
return is_unbounded_array(ns.follow_tag(to_struct_tag_type(type)));
522+
else if(type.id() == ID_union_tag)
523+
return is_unbounded_array(ns.follow_tag(to_union_tag_type(type)));
524+
else if(type.id() == ID_struct)
525+
{
526+
for(const auto &component : to_struct_type(type).components())
527+
{
528+
if(is_unbounded_array(component.type()))
529+
return true;
530+
}
531+
532+
return false;
533+
}
534+
else if(type.id() == ID_union)
535+
{
536+
for(const auto &component : to_union_type(type).components())
537+
{
538+
if(is_unbounded_array(component.type()))
539+
return true;
540+
}
541+
542+
return false;
543+
}
544+
else if(type.id() != ID_array)
521545
return false;
522546

523547
if(unbounded_array==unbounded_arrayt::U_ALL)

src/solvers/flattening/boolbv_byte_extract.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@ bvt map_bv(const endianness_mapt &map, const bvt &src)
3434

3535
bvt boolbvt::convert_byte_extract(const byte_extract_exprt &expr)
3636
{
37+
const auto &width_opt = bv_width.get_width_opt(expr.type());
38+
3739
// array logic does not handle byte operators, thus lower when operating on
3840
// unbounded arrays
39-
if(is_unbounded_array(expr.op().type()))
41+
if(
42+
is_unbounded_array(expr.op().type()) || is_unbounded_array(expr.type()) ||
43+
!width_opt.has_value())
4044
{
4145
return convert_bv(lower_byte_extract(expr, ns));
4246
}
4347

44-
const std::size_t width = boolbv_width(expr.type());
48+
const std::size_t width = *width_opt;
4549

4650
// special treatment for bit-fields and big-endian:
4751
// we need byte granularity

src/solvers/flattening/boolbv_union.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,20 @@ Author: Daniel Kroening, [email protected]
1010

1111
bvt boolbvt::convert_union(const union_exprt &expr)
1212
{
13-
std::size_t width=boolbv_width(expr.type());
13+
const auto &width_opt = bv_width.get_width_opt(expr.type());
1414

1515
const bvt &op_bv=convert_bv(expr.op());
1616

1717
INVARIANT(
18-
op_bv.size() <= width,
18+
!width_opt.has_value() || op_bv.size() <= *width_opt,
1919
"operand bitvector width shall not be larger than the width indicated by "
2020
"the union type");
2121

2222
bvt bv;
23-
bv.resize(width);
23+
if(width_opt.has_value())
24+
bv.resize(*width_opt);
25+
else
26+
bv.resize(op_bv.size());
2427

2528
endianness_mapt map_u = endianness_map(expr.type());
2629
endianness_mapt map_op = endianness_map(expr.op().type());

0 commit comments

Comments
 (0)