-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathSuspiciousCallToMemset.ql
More file actions
144 lines (137 loc) · 4.33 KB
/
SuspiciousCallToMemset.ql
File metadata and controls
144 lines (137 loc) · 4.33 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* @name Suspicious call to memset
* @description Use of memset where the size argument is computed as the size of
* some non-struct type. When initializing a buffer, you should specify
* its size as `<number of elements> * <size of one element>` to ensure
* portability.
* @kind problem
* @id cpp/suspicious-call-to-memset
* @problem.severity recommendation
* @security-severity 10.0
* @precision medium
* @tags reliability
* correctness
* security
* external/cwe/cwe-676
*/
import cpp
/**
* Holds if `e` is a `sizeof` expression on type `t`, with
* optional multiplication by a constant.
*/
predicate sizeOfExpr(Expr e, Type t) {
t = e.(SizeofTypeOperator).getTypeOperand()
or
t = e.(SizeofExprOperator).getExprOperand().getType()
or
sizeOfExpr(e.(MulExpr).getAnOperand(), t) and
e.(MulExpr).getAnOperand() instanceof Literal
}
/**
* Gets the type `t` with typedefs, array types and references removed.
*
* This is similar to `Type.stripType` except that it doesn't remove
* a `PointerType`.
*/
Type stripType(Type t) {
result = stripType(t.(TypedefType).getBaseType())
or
result = stripType(t.(ArrayType).getBaseType())
or
result = stripType(t.(ReferenceType).getBaseType())
or
result = stripType(t.(SpecifiedType).getBaseType())
or
result = stripType(t.(Decltype).getBaseType())
or
result = stripType(t.(TypeofType).getBaseType())
or
result = stripType(t.(IntrinsicTransformedType).getBaseType())
or
not t instanceof TypedefType and
not t instanceof ArrayType and
not t instanceof ReferenceType and
not t instanceof SpecifiedType and
not t instanceof Decltype and
not t instanceof TypeofType and
not t instanceof IntrinsicTransformedType and
result = t
}
/**
* Holds if `t` points to `base` via a specified number of levels of pointer
* indirection. Intermediate typedefs and array types are allowed. Note that
* `base` is a stripped type (via `stripType`).
*/
predicate pointerIndirection(Type t, int indirection, Type base) {
base = stripType(t) and
not base instanceof PointerType and
indirection = 0
or
pointerIndirection(stripType(t).(PointerType).getBaseType(), indirection - 1, base)
}
/**
* Holds if `t` points to a non-pointer, non-array type via a specified number
* of levels of pointer indirection. Intermediate typedefs and array types are
* allowed.
*/
predicate pointerIndirection2(Type t, int indirection) {
not stripType(t) instanceof PointerType and
indirection = 0
or
pointerIndirection2(stripType(t).(PointerType).getBaseType(), indirection - 1)
}
/**
* Holds if `memset(dataArg, _, sizeArg)`, where `sizeArg` has the form
* `sizeof(type)`, could be reasonable.
*/
predicate reasonableMemset(FunctionCall fc) {
exists(Expr dataArg, Expr sizeArg |
dataArg = fc.getArgument(0) and
sizeArg = fc.getArgument(2) and
exists(Type dataType, Type sizeOfType |
dataType = dataArg.getType() and
sizeOfExpr(sizeArg, sizeOfType) and
exists(int i |
exists(Type base |
// memset(&t, _, sizeof(t))
pointerIndirection(dataType, i + 1, base) and
pointerIndirection(sizeOfType, i, base)
)
or
exists(Type base |
// memset(t[n], _, sizeof(t))
pointerIndirection(dataType.getUnspecifiedType().(ArrayType), i, base) and
pointerIndirection(sizeOfType, i, base)
)
or
exists(VoidType vt |
// memset(void *, _, sizeof(t))
pointerIndirection(dataType, i + 1, vt) and
pointerIndirection2(sizeOfType, i)
)
or
exists(Type ct |
// memset(char *, _, sizeof(t)) and similar
ct.getSize() = 1 and
pointerIndirection(dataType, i + 1, ct) and
pointerIndirection2(sizeOfType, i)
)
or
exists(Type ct |
// memset(char [], _, sizeof(t)) and similar
ct.getSize() = 1 and
pointerIndirection(dataType.getUnspecifiedType().(ArrayType), i, ct) and
pointerIndirection2(sizeOfType, i)
)
)
)
)
}
from FunctionCall fc, Type t
where
fc.getTarget().hasName("memset") and
sizeOfExpr(fc.getArgument(2), t) and
not reasonableMemset(fc)
select fc,
"The size of the memory area set by memset should not be the size of the type " + t.getName() +
"."