Skip to content

Commit efea5c4

Browse files
committed
Fix flattening of access beyond type-specified bounds
The test Pointer_byte_extract5 was previously only solved properly thanks to hacks in the simplifier. We should not have to rely on those. Also adjust the malloc size computation to not rely on absence of padding.
1 parent 0ec87c8 commit efea5c4

File tree

5 files changed

+71
-6
lines changed

5 files changed

+71
-6
lines changed

regression/cbmc/Pointer_byte_extract5/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ typedef struct
2222

2323
int main()
2424
{
25-
Struct3 *p = malloc (sizeof (int) + 2 * sizeof(Union));
25+
Struct3 *p = malloc(sizeof(Struct3) + sizeof(Union));
2626
p->Count = 3;
2727
int po=0;
2828

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--bounds-check --32 --no-simplify
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
array\.List dynamic object upper bound in p->List\[2\]: FAILURE
7+
\*\* 1 of 14 failed
8+
--
9+
^warning: ignoring
10+
--
11+
Test is built from SV-COMP's memsafety/20051113-1.c_false-valid-memtrack.c.
12+
C90 did not have flexible arrays, and using arrays of size 1 was common
13+
practice: http://c-faq.com/struct/structhack.html. We need to treat those as if
14+
it were a zero-sized array.

regression/cbmc/Pointer_byte_extract5/test.desc

+5
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ array\.List dynamic object upper bound in p->List\[2\]: FAILURE
77
\*\* 1 of 11 failed
88
--
99
^warning: ignoring
10+
--
11+
Test is built from SV-COMP's memsafety/20051113-1.c_false-valid-memtrack.c.
12+
C90 did not have flexible arrays, and using arrays of size 1 was common
13+
practice: http://c-faq.com/struct/structhack.html. We need to treat those as if
14+
it were a zero-sized array.

src/solvers/flattening/boolbv_byte_extract.cpp

+28-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <util/arith_tools.h>
1414
#include <util/byte_operators.h>
15+
#include <util/pointer_offset_size.h>
1516
#include <util/std_expr.h>
1617
#include <util/throw_with_nested.h>
1718

@@ -78,6 +79,30 @@ bvt boolbvt::convert_byte_extract(const byte_extract_exprt &expr)
7879
if(width==0)
7980
return conversion_failed(expr);
8081

82+
// see if the byte number is constant and within bounds, else work from the
83+
// root object
84+
const mp_integer op_bytes = pointer_offset_size(expr.op().type(), ns);
85+
auto index = numeric_cast<mp_integer>(expr.offset());
86+
if(
87+
(!index.has_value() || (*index < 0 || *index >= op_bytes)) &&
88+
(expr.op().id() == ID_member || expr.op().id() == ID_index ||
89+
expr.op().id() == ID_byte_extract_big_endian ||
90+
expr.op().id() == ID_byte_extract_little_endian))
91+
{
92+
object_descriptor_exprt o;
93+
o.build(expr.op(), ns);
94+
CHECK_RETURN(o.offset().id() != ID_unknown);
95+
if(o.offset().type() != expr.offset().type())
96+
o.offset().make_typecast(expr.offset().type());
97+
byte_extract_exprt be(
98+
expr.id(),
99+
o.root_object(),
100+
plus_exprt(o.offset(), expr.offset()),
101+
expr.type());
102+
103+
return convert_bv(be);
104+
}
105+
81106
const exprt &op=expr.op();
82107
const exprt &offset=expr.offset();
83108

@@ -106,13 +131,12 @@ bvt boolbvt::convert_byte_extract(const byte_extract_exprt &expr)
106131
// see if the byte number is constant
107132
unsigned byte_width=8;
108133

109-
mp_integer index;
110-
if(!to_integer(offset, index))
134+
if(index.has_value())
111135
{
112-
if(index<0)
136+
if(*index < 0)
113137
throw "byte_extract flatting with negative offset: "+expr.pretty();
114138

115-
mp_integer offset=index*byte_width;
139+
const mp_integer offset = *index * byte_width;
116140

117141
std::size_t offset_i=integer2unsigned(offset);
118142

src/solvers/flattening/boolbv_index.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ Author: Daniel Kroening, [email protected]
1111
#include <cassert>
1212

1313
#include <util/arith_tools.h>
14-
#include <util/std_expr.h>
14+
#include <util/pointer_offset_size.h>
1515
#include <util/simplify_expr.h>
16+
#include <util/std_expr.h>
1617

1718
bvt boolbvt::convert_index(const index_exprt &expr)
1819
{
@@ -333,6 +334,27 @@ bvt boolbvt::convert_index(
333334
for(std::size_t i=0; i<width; i++)
334335
bv[i]=tmp[integer2size_t(offset+i)];
335336
}
337+
else if(
338+
array.id() == ID_member || array.id() == ID_index ||
339+
array.id() == ID_byte_extract_big_endian ||
340+
array.id() == ID_byte_extract_little_endian)
341+
{
342+
object_descriptor_exprt o;
343+
o.build(array, ns);
344+
CHECK_RETURN(o.offset().id() != ID_unknown);
345+
346+
const mp_integer subtype_bytes =
347+
pointer_offset_size(array_type.subtype(), ns);
348+
exprt new_offset = simplify_expr(
349+
plus_exprt(
350+
o.offset(), from_integer(index * subtype_bytes, o.offset().type())),
351+
ns);
352+
353+
byte_extract_exprt be(
354+
byte_extract_id(), o.root_object(), new_offset, array_type.subtype());
355+
356+
return convert_bv(be);
357+
}
336358
else
337359
{
338360
// out of bounds

0 commit comments

Comments
 (0)