Skip to content

Commit 05ef589

Browse files
authored
Merge pull request #433 from rdmarsh2/rdmarsh/cpp/buffersize-backport
C++: Backport "Improve memberMayBeVarSize" to rc/1.18
2 parents f159c7e + 57dafe2 commit 05ef589

File tree

1 file changed

+29
-27
lines changed

1 file changed

+29
-27
lines changed

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

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,5 @@
11
import cpp
22

3-
/**
4-
* Holds if `sizeof(s)` occurs as part of the parameter of a dynamic
5-
* memory allocation (`malloc`, `realloc`, etc.), except if `sizeof(s)`
6-
* only ever occurs as the immediate parameter to allocations.
7-
*
8-
* For example, holds for `s` if it occurs as
9-
* ```
10-
* malloc(sizeof(s) + 100 * sizeof(char))
11-
* ```
12-
* but not if it only ever occurs as
13-
* ```
14-
* malloc(sizeof(s))
15-
* ```
16-
*/
17-
private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
18-
exists(SizeofTypeOperator sof |
19-
sof.getTypeOperand().getUnspecifiedType() = s |
20-
// Check all ancestor nodes except the immediate parent for
21-
// allocations.
22-
isStdLibAllocationExpr(sof.getParent().(Expr).getParent+())
23-
)
24-
}
25-
263
/**
274
* Holds if `v` is a member variable of `c` that looks like it might be variable sized in practice. For
285
* example:
@@ -33,15 +10,40 @@ private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
3310
* };
3411
* ```
3512
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. In addition,
36-
* there must be at least one instance where a `c` pointer is allocated with additional space.
13+
* there must be at least one instance where a `c` pointer is allocated with additional space. For
14+
* example, holds for `c` if it occurs as
15+
* ```
16+
* malloc(sizeof(c) + 100 * sizeof(char))
17+
* ```
18+
* but not if it only ever occurs as
19+
* ```
20+
* malloc(sizeof(c))
21+
* ```
3722
*/
3823
predicate memberMayBeVarSize(Class c, MemberVariable v) {
3924
exists(int i |
25+
// `v` is the last field in `c`
4026
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
4127
v = c.getCanonicalMember(i) and
42-
v.getType().getUnspecifiedType().(ArrayType).getSize() <= 1
43-
) and
44-
isDynamicallyAllocatedWithDifferentSize(c)
28+
29+
// v is an array of size at most 1
30+
v.getType().getUnspecifiedType().(ArrayType).getArraySize() <= 1
31+
) and (
32+
exists(SizeofOperator so |
33+
// `sizeof(c)` is taken
34+
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
35+
so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = c |
36+
37+
// arithmetic is performed on the result
38+
so.getParent*() instanceof AddExpr
39+
) or exists(AddressOfExpr aoe |
40+
// `&(c.v)` is taken
41+
aoe.getAddressable() = v
42+
) or exists(BuiltInOperationOffsetOf oo |
43+
// `offsetof(c, v)` using a builtin
44+
oo.getAChild().(VariableAccess).getTarget() = v
45+
)
46+
)
4547
}
4648

4749
/**

0 commit comments

Comments
 (0)