Skip to content

Commit 20f8beb

Browse files
committed
Add regression test to ascertain struct hack support
When a struct with a C90-style flexible array member (e.g., `char data[1]`, aka "struct hack") was allocated with extra space using `malloc(sizeof(struct Foo) + sizeof(char)*2)`, CBMC before 78839a9 incorrectly failed assertions when accessing elements beyond the declared array size. Co-authored-by: Kiro autonomous agent Fixes: #5213
1 parent 76dd20f commit 20f8beb

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <assert.h>
2+
#include <malloc.h>
3+
4+
// Reproduction case for struct hack bug reported for CBMC 5.12
5+
// Bug: When a struct with a flexible array member is allocated with extra
6+
// space, CBMC incorrectly fails assertions when accessing elements beyond
7+
// the declared size.
8+
9+
struct Foo
10+
{
11+
int i;
12+
char data[1];
13+
};
14+
15+
int main()
16+
{
17+
struct Foo *foo = malloc(sizeof(struct Foo) + sizeof(char) * 2);
18+
assert(foo);
19+
foo->data[0] = 'a';
20+
assert(foo->data[0] == 'a'); // always succeeds
21+
foo->data[1] = 'b'; // set data[1]
22+
assert(foo->data[1] == 'b'); // check data[1] -- should succeed
23+
foo->data[2] = 'c'; // set data[2]
24+
assert(
25+
foo->data[1] == 'b'); // check data[1] again - this used to fail in 5.12
26+
27+
return 0;
28+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
CORE
2+
main.c
3+
--no-malloc-may-fail
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
9+
--
10+
Regression test for GitHub issue #8617.
11+
Exact reproduction of the struct hack bug reported for CBMC 5.12.
12+
13+
In the original bug report, when a struct with a flexible array member
14+
(char data[1]) was allocated with extra space via
15+
malloc(sizeof(struct Foo) + sizeof(char)*2), CBMC would incorrectly fail
16+
the assertion assert(foo->data[1]=='b') after setting foo->data[2]='c'.
17+
18+
This was caused by incorrect handling of byte_extract operations for
19+
flexible array members. Array operations may fall back to byte_extract
20+
expressions, and without proper simplification, accesses to dynamically
21+
allocated extra memory beyond the declared struct size would fail.
22+
23+
Fixed in CBMC 6.7.0 by commit 78839a978c which improved simplification
24+
of byte_extract operations to handle multiple-of-element size accesses
25+
to arrays correctly, converting them to index expressions when the offset
26+
is known to be a multiple of the array-element size.
27+
28+
Note: C90 did not have flexible arrays, and using arrays of size 1 was
29+
common practice (the "struct hack"). While this is technically undefined
30+
behavior in C99+, CBMC now handles this pattern correctly.

0 commit comments

Comments
 (0)