Skip to content

Commit b08eabe

Browse files
committed
C++: Relax predicate memberMayBeVarSize to mark all members of size 0 or 1 as variable sized
1 parent a4a9e2a commit b08eabe

File tree

1 file changed

+3
-47
lines changed

1 file changed

+3
-47
lines changed

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

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,11 @@ import semmle.code.cpp.dataflow.DataFlow
1010
* char data[1]; // v
1111
* };
1212
* ```
13-
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`.
14-
* In addition, if the size of the structure is taken, there must be at least one instance
15-
* where a `c` pointer is allocated with additional space.
16-
* For example, holds for `c` if it occurs as
17-
* ```
18-
* malloc(sizeof(c) + 100 * sizeof(char))
19-
* ```
20-
* but not if it only ever occurs as
21-
* ```
22-
* malloc(sizeof(c))
23-
* ```
13+
* This requires that `v` is an array of size 0 or 1.
2414
*/
2515
predicate memberMayBeVarSize(Class c, MemberVariable v) {
26-
exists(int i |
27-
// `v` is the last field in `c`
28-
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
29-
v = c.getCanonicalMember(i) and
30-
// v is an array of size at most 1
31-
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
32-
not c instanceof Union
33-
) and
34-
// If the size is taken, then arithmetic is performed on the result at least once
35-
(
36-
// `sizeof(c)` is not taken
37-
not exists(SizeofOperator so |
38-
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
39-
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
40-
)
41-
or
42-
// or `sizeof(c)` is taken
43-
exists(SizeofOperator so |
44-
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
45-
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
46-
|
47-
// and arithmetic is performed on the result
48-
so.getParent*() instanceof AddExpr
49-
)
50-
)
16+
c = v.getDeclaringType() and
17+
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
5118
}
5219

5320
/**
@@ -60,10 +27,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
6027
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
6128
why = bufferVar and
6229
not memberMayBeVarSize(_, bufferVar) and
63-
not exists(Union bufferType |
64-
bufferType.getAMemberVariable() = why and
65-
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
66-
) and
6730
not result = 0 // zero sized arrays are likely to have special usage, for example
6831
or
6932
// behaving a bit like a 'union' overlapping other fields.
@@ -85,13 +48,6 @@ int getBufferSize(Expr bufferExpr, Element why) {
8548
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
8649
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
8750
)
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-
)
9551
)
9652
or
9753
// buffer is a fixed size dynamic allocation

0 commit comments

Comments
 (0)