Skip to content

Commit 306b711

Browse files
authored
Merge pull request #368 from geoffw0/buffersize
CPP: Improve memberMayBeVarSize
2 parents 35a5bca + 2f517de commit 306b711

File tree

2 files changed

+30
-27
lines changed

2 files changed

+30
-27
lines changed

change-notes/1.19/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@
2525
## Changes to QL libraries
2626

2727
* Added a hash consing library for structural comparison of expressions.
28+
* `getBufferSize` now detects variable size structs more reliably.

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

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
11
import cpp
22
import semmle.code.cpp.dataflow.DataFlow
33

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

4850
/**

0 commit comments

Comments
 (0)