Skip to content

Commit 342b2df

Browse files
committed
C++: zero or one byte sized arrays in unions are considered as having the length of the union its a member of
1 parent 3172d57 commit 342b2df

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
2828
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
2929
v = c.getCanonicalMember(i) and
3030
// v is an array of size at most 1
31-
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
31+
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
32+
not c instanceof Union
3233
) and
3334
// If the size is taken, then arithmetic is performed on the result at least once
3435
(
@@ -59,6 +60,10 @@ int getBufferSize(Expr bufferExpr, Element why) {
5960
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
6061
why = bufferVar and
6162
not memberMayBeVarSize(_, bufferVar) and
63+
not exists(Union bufferType |
64+
bufferType.getAMemberVariable() = why and
65+
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
66+
) and
6267
not result = 0 // zero sized arrays are likely to have special usage, for example
6368
or
6469
// behaving a bit like a 'union' overlapping other fields.
@@ -80,6 +85,13 @@ int getBufferSize(Expr bufferExpr, Element why) {
8085
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
8186
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
8287
)
88+
or
89+
exists(Union bufferType |
90+
bufferType.getAMemberVariable() = why and
91+
why = bufferVar and
92+
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1 and
93+
result = bufferType.getSize()
94+
)
8395
)
8496
or
8597
// buffer is a fixed size dynamic allocation

cpp/ql/test/query-tests/Critical/OverflowStatic/OverflowStatic.expected

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@
1111
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' is accessed here. |
1212
| test.c:39:3:39:11 | access to array | Potential buffer-overflow: 'buf' has size 1 but 'buf[7]' is accessed here. |
1313
| test.c:40:3:40:11 | access to array | Potential buffer-overflow: 'buf' has size 1 but 'buf[8]' is accessed here. |
14-
| test.c:51:3:51:20 | access to array | Potential buffer-overflow: 'ptr' has size 1 but 'ptr[7]' is accessed here. |
15-
| test.c:52:3:52:18 | access to array | Potential buffer-overflow: 'ptr' has size 1 but 'ptr[8]' is accessed here. |
16-
| test.c:58:3:58:28 | access to array | Potential buffer-overflow: 'ptr' has size 1 but 'ptr[7]' is accessed here. |
17-
| test.c:59:3:59:26 | access to array | Potential buffer-overflow: 'ptr' has size 1 but 'ptr[8]' is accessed here. |
18-
| test.c:65:3:65:20 | access to array | Potential buffer-overflow: 'ptr' has size 1 but 'ptr[7]' is accessed here. |
19-
| test.c:66:3:66:18 | access to array | Potential buffer-overflow: 'ptr' has size 1 but 'ptr[8]' is accessed here. |
14+
| test.c:52:3:52:18 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
15+
| test.c:59:3:59:26 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
16+
| test.c:66:3:66:18 | access to array | Potential buffer-overflow: 'ptr' has size 8 but 'ptr[8]' is accessed here. |
2017
| test.c:72:3:72:11 | access to array | Potential buffer-overflow: 'buf' has size 1 but 'buf[1]' is accessed here. |
2118
| test.cpp:19:3:19:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer1' has 3 elements. |
2219
| test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. |

cpp/ql/test/query-tests/Critical/OverflowStatic/test.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,21 @@ union u {
4848
void union_test() {
4949
union u u;
5050
u.ptr[0] = 0; // GOOD
51-
u.ptr[sizeof(u)-1] = 0; // GOOD [FALSE POSITIVE]
51+
u.ptr[sizeof(u)-1] = 0; // GOOD
5252
u.ptr[sizeof(u)] = 0; // BAD
5353
}
5454

5555
void test_struct_union() {
5656
struct { union u u; } v;
5757
v.u.ptr[0] = 0; // GOOD
58-
v.u.ptr[sizeof(union u)-1] = 0; // GOOD [FALSE POSITIVE]
58+
v.u.ptr[sizeof(union u)-1] = 0; // GOOD
5959
v.u.ptr[sizeof(union u)] = 0; // BAD
6060
}
6161

6262
void union_test2() {
6363
union { char ptr[1]; unsigned long value; } u;
6464
u.ptr[0] = 0; // GOOD
65-
u.ptr[sizeof(u)-1] = 0; // GOOD [FALSE POSITIVE]
65+
u.ptr[sizeof(u)-1] = 0; // GOOD
6666
u.ptr[sizeof(u)] = 0; // BAD
6767
}
6868

0 commit comments

Comments
 (0)