-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathAllocStructsWithAFlexibleArrayMemberDynamically.ql
89 lines (79 loc) · 3.15 KB
/
AllocStructsWithAFlexibleArrayMemberDynamically.ql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
* @id c/cert/alloc-structs-with-a-flexible-array-member-dynamically
* @name MEM33-C: Allocate structures containing a flexible array member dynamically
* @description A structure containing a flexible array member must be allocated dynamically in
* order for subsequent accesses to the flexible array to point to valid memory.
* @kind problem
* @precision very-high
* @problem.severity error
* @tags external/cert/id/mem33-c
* correctness
* external/cert/obligation/rule
*/
import cpp
import codingstandards.c.cert
import codingstandards.c.Variable
import codingstandards.c.Objects
import semmle.code.cpp.models.interfaces.Allocation
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
abstract class FlexibleArrayAlloc extends Element {
/**
* Returns the `Variable` being allocated.
*/
abstract Element getReportElement();
}
/**
* A `FunctionCall` to an `AllocationFunction` that allocates memory
* which is assigned to a `Variable` of type `FlexibleArrayStructType`.
*/
class FlexibleArrayStructDynamicAlloc extends FlexibleArrayAlloc, FunctionCall {
Variable v;
FlexibleArrayStructDynamicAlloc() {
this.getTarget() instanceof AllocationFunction and
v.getAnAssignedValue() = this and
v.getUnderlyingType().(PointerType).getBaseType().getUnspecifiedType() instanceof
FlexibleArrayStructType
}
/**
* Holds if the size argument of the allocation function is insufficient to
* allocate at least one byte for the flexible array member.
*/
predicate hasInsufficientAllocationSize() {
upperBound(this.getArgument(this.getTarget().(AllocationFunction).getSizeArg())) <=
max(v.getUnderlyingType()
.(PointerType)
.getBaseType()
.getUnspecifiedType()
.(FlexibleArrayStructType)
.getSize()
)
}
override Element getReportElement() { result = v }
}
/**
* A `Variable` of type `FlexibleArrayStructType` that is not allocated dynamically.
*/
class FlexibleArrayNonDynamicAlloc extends FlexibleArrayAlloc {
ObjectIdentity object;
FlexibleArrayNonDynamicAlloc() {
this = object and
not object.getStorageDuration().isAllocated() and
// Exclude temporaries. Though they should violate this rule, in practice these results are
// often spurious and redundant, such as (*x = *x) which creates an unused temporary object.
not object.hasTemporaryLifetime() and
object.getType().getUnspecifiedType() instanceof FlexibleArrayStructType and
not exists(Variable v | v.getInitializer().getExpr() = this)
}
override Element getReportElement() { result = object }
}
from FlexibleArrayAlloc alloc, string message
where
not isExcluded(alloc, Memory2Package::allocStructsWithAFlexibleArrayMemberDynamicallyQuery()) and
(
alloc.(FlexibleArrayStructDynamicAlloc).hasInsufficientAllocationSize() and
message = "$@ allocated with insufficient memory for its flexible array member."
or
alloc instanceof FlexibleArrayNonDynamicAlloc and
message = "$@ contains a flexible array member but is not dynamically allocated."
)
select alloc, message, alloc.getReportElement(), alloc.getReportElement().toString()