Skip to content

Commit 16c64cf

Browse files
authored
Merge pull request #4324 from tautschnig/flexible-array-fix
Fix bounds checking for structs with flexible array members
2 parents 9eb9d70 + ae0a1f3 commit 16c64cf

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

regression/cbmc/struct12/main.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
struct S
5+
{
6+
int a;
7+
char b[];
8+
};
9+
10+
int main()
11+
{
12+
struct S *s = malloc(sizeof(struct S) + 1);
13+
// allocate an object that matches the fixed size of the struct, without the
14+
// flexible member
15+
int *p = malloc(sizeof(int));
16+
s->b[0] = 0;
17+
assert(s->b[0] == 0);
18+
}

regression/cbmc/struct12/test.desc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
--pointer-check --bounds-check
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Our logic for constructing assertion over structs with flexible array members
11+
was wrong, because it could conflate dynamic allocation sizes across different
12+
objects.

src/analyses/goto_check.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,8 +1333,22 @@ void goto_checkt::bounds_check(
13331333
auto type_size_opt = size_of_expr(ode.root_object().type(), ns);
13341334

13351335
if(type_size_opt.has_value())
1336-
type_matches_size =
1337-
equal_exprt(size, typecast_exprt(type_size_opt.value(), size.type()));
1336+
{
1337+
// Build a predicate that evaluates to true iff the size reported by
1338+
// sizeof (i.e., compile-time size) matches the actual run-time size. The
1339+
// run-time size for a dynamic (i.e., heap-allocated) object is determined
1340+
// by the dynamic_size(ns) expression, which can only be used when
1341+
// malloc_object(pointer, ns) evaluates to true for a given pointer.
1342+
type_matches_size = if_exprt{
1343+
dynamic_object(pointer),
1344+
and_exprt{malloc_object(pointer, ns),
1345+
equal_exprt{typecast_exprt::conditional_cast(
1346+
dynamic_size(ns), type_size_opt->type()),
1347+
*type_size_opt}},
1348+
equal_exprt{typecast_exprt::conditional_cast(
1349+
object_size(pointer), type_size_opt->type()),
1350+
*type_size_opt}};
1351+
}
13381352
}
13391353

13401354
const exprt &size=array_type.id()==ID_array ?

0 commit comments

Comments
 (0)