11import cpp
22import 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 */
3924predicate 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