forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOverflowStatic.ql
More file actions
137 lines (122 loc) · 4.08 KB
/
OverflowStatic.ql
File metadata and controls
137 lines (122 loc) · 4.08 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
/**
* @name Static array access may cause overflow
* @description Exceeding the size of a static array during write or access operations
* may result in a buffer overflow.
* @kind problem
* @problem.severity warning
* @precision medium
* @id cpp/static-buffer-overflow
* @tags reliability
* security
* external/cwe/cwe-119
* external/cwe/cwe-131
*/
import cpp
import semmle.code.cpp.commons.Buffer
import LoopBounds
private predicate staticBufferBase(VariableAccess access, Variable v) {
v.getType().(ArrayType).getBaseType() instanceof CharType and
access = v.getAnAccess() and
not memberMayBeVarSize(_, v)
}
predicate staticBuffer(VariableAccess access, Variable v, int size) {
staticBufferBase(access, v) and
size = getBufferSize(access, _)
}
class BufferAccess extends ArrayExpr {
BufferAccess() {
exists(int size |
staticBuffer(this.getArrayBase(), _, size) and
size != 0
) and
// exclude accesses in macro implementation of `strcmp`,
// which are carefully controlled but can look dangerous.
not exists(Macro m |
m.getName() = "strcmp" and
m.getAnInvocation().getAnExpandedElement() = this
)
}
int bufferSize() { staticBuffer(this.getArrayBase(), _, result) }
Variable buffer() { result.getAnAccess() = this.getArrayBase() }
}
predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
exists(ClassicForLoop loop |
loop.getStmt().getAChild*() = bufaccess.getEnclosingStmt() and
loop.limit() >= bufaccess.bufferSize() and
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
msg =
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
bufaccess.bufferSize().toString() + " elements."
)
}
predicate bufferAndSizeFunction(Function f, int buf, int size) {
f.hasGlobalName("read") and buf = 1 and size = 2
or
f.hasGlobalOrStdName("fgets") and buf = 0 and size = 1
or
f.hasGlobalOrStdName("strncpy") and buf = 0 and size = 2
or
f.hasGlobalOrStdName("strncat") and buf = 0 and size = 2
or
f.hasGlobalOrStdName("memcpy") and buf = 0 and size = 2
or
f.hasGlobalOrStdName("memmove") and buf = 0 and size = 2
or
f.hasGlobalOrStdName("snprintf") and buf = 0 and size = 1
or
f.hasGlobalOrStdName("vsnprintf") and buf = 0 and size = 1
}
class CallWithBufferSize extends FunctionCall {
CallWithBufferSize() { bufferAndSizeFunction(this.getTarget(), _, _) }
Expr buffer() {
exists(int i |
bufferAndSizeFunction(this.getTarget(), i, _) and
result = this.getArgument(i)
)
}
Expr statedSizeExpr() {
exists(int i |
bufferAndSizeFunction(this.getTarget(), _, i) and
result = this.getArgument(i)
)
}
int statedSizeValue() {
exists(Expr statedSizeSrc |
DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr()) and
result = statedSizeSrc.getValue().toInt()
)
}
}
predicate wrongBufferSize(Expr error, string msg) {
exists(CallWithBufferSize call, int bufsize, Variable buf, int statedSize |
staticBuffer(call.buffer(), buf, bufsize) and
statedSize = min(call.statedSizeValue()) and
statedSize > bufsize and
error = call.statedSizeExpr() and
msg =
"Potential buffer-overflow: '" + buf.getName() + "' has size " + bufsize.toString() + " not " +
statedSize + "."
)
}
predicate outOfBounds(BufferAccess bufaccess, string msg) {
exists(int size, int access, string buf |
buf = bufaccess.buffer().getName() and
bufaccess.bufferSize() = size and
bufaccess.getArrayOffset().getValue().toInt() = access and
(
access > size
or
access = size and not exists(AddressOfExpr addof | bufaccess = addof.getOperand())
) and
msg =
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
access.toString() + "]' is accessed here."
)
}
from Element error, string msg
where
overflowOffsetInLoop(error, msg) or
wrongBufferSize(error, msg) or
outOfBounds(error, msg)
select error, msg