Skip to content

Commit e32f7d8

Browse files
committed
C++: Speed up analysis on 'Samate' by avoiding the 'Variable' column in the dataflow stages of the query.
1 parent 600c60a commit e32f7d8

File tree

2 files changed

+55
-31
lines changed

2 files changed

+55
-31
lines changed

cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -78,28 +78,39 @@ predicate isInvalidPointerDerefSink2(DataFlow::Node sink, Instruction i, string
7878
)
7979
}
8080

81+
predicate arrayTypeCand(ArrayType arrayType) { any(Variable v).getUnspecifiedType() = arrayType }
82+
8183
pragma[nomagic]
8284
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int arraySize) {
85+
arrayTypeCand(arr) and
8386
arr.getBaseType().getSize() = baseTypeSize and
8487
arr.getArraySize() = arraySize
8588
}
8689

87-
predicate pointerArithOverflow0(
88-
PointerArithmeticInstruction pai, Variable v, int size, int bound, int delta
89-
) {
90-
not v.getNamespace() instanceof StdNamespace and
91-
arrayTypeHasSizes(v.getUnspecifiedType(), pai.getElementSize(), size) and
92-
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound b), bound, true, _) and
90+
bindingset[pai]
91+
pragma[inline_late]
92+
predicate constantUpperBounded(PointerArithmeticInstruction pai, int delta) {
93+
semBounded(getSemanticExpr(pai.getRight()), any(SemZeroBound b), delta, true, _)
94+
}
95+
96+
bindingset[pai, size]
97+
predicate pointerArithOverflow0Impl(PointerArithmeticInstruction pai, int size, int bound, int delta) {
98+
constantUpperBounded(pai, bound) and
9399
delta = bound - size and
94100
delta >= 0 and
95101
size != 0 and
96102
size != 1
97103
}
98104

105+
predicate pointerArithOverflow0(PointerArithmeticInstruction pai, int delta) {
106+
exists(int size, int bound |
107+
arrayTypeHasSizes(_, pai.getElementSize(), size) and
108+
pointerArithOverflow0Impl(pai, size, bound, delta)
109+
)
110+
}
111+
99112
module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
100-
predicate isSource(DataFlow::Node source) {
101-
pointerArithOverflow0(source.asInstruction(), _, _, _, _)
102-
}
113+
predicate isSource(DataFlow::Node source) { pointerArithOverflow0(source.asInstruction(), _) }
103114

104115
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
105116

@@ -110,30 +121,38 @@ module PointerArithmeticToDerefConfig implements DataFlow::ConfigSig {
110121

111122
module PointerArithmeticToDerefFlow = DataFlow::Global<PointerArithmeticToDerefConfig>;
112123

113-
predicate pointerArithOverflow(
114-
PointerArithmeticInstruction pai, Variable v, int size, int bound, int delta
115-
) {
116-
pointerArithOverflow0(pai, v, size, bound, delta) and
124+
predicate pointerArithOverflow(PointerArithmeticInstruction pai, int delta) {
125+
pointerArithOverflow0(pai, delta) and
117126
PointerArithmeticToDerefFlow::flow(DataFlow::instructionNode(pai), _)
118127
}
119128

129+
bindingset[v]
130+
predicate finalPointerArithOverflow(Variable v, PointerArithmeticInstruction pai, int delta) {
131+
exists(int size |
132+
arrayTypeHasSizes(pragma[only_bind_out](v.getUnspecifiedType()), pai.getElementSize(), size) and
133+
pointerArithOverflow0Impl(pai, size, _, delta)
134+
)
135+
}
136+
137+
predicate isSourceImpl(DataFlow::Node source, Variable v) {
138+
(
139+
source.asInstruction().(FieldAddressInstruction).getField() = v
140+
or
141+
source.asInstruction().(VariableAddressInstruction).getAstVariable() = v
142+
) and
143+
exists(v.getUnspecifiedType().(ArrayType).getArraySize())
144+
}
145+
120146
module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig {
121147
newtype FlowState =
122-
additional TArray(Variable v) { pointerArithOverflow(_, v, _, _, _) } or
148+
additional TArray() or
123149
additional TOverflowArithmetic(PointerArithmeticInstruction pai) {
124-
pointerArithOverflow(pai, _, _, _, _)
150+
pointerArithOverflow(pai, _)
125151
}
126152

127153
predicate isSource(DataFlow::Node source, FlowState state) {
128-
exists(Variable v |
129-
(
130-
source.asInstruction().(FieldAddressInstruction).getField() = v
131-
or
132-
source.asInstruction().(VariableAddressInstruction).getAstVariable() = v
133-
) and
134-
exists(v.getUnspecifiedType().(ArrayType).getArraySize()) and
135-
state = TArray(v)
136-
)
154+
isSourceImpl(source, _) and
155+
state = TArray()
137156
}
138157

139158
predicate isSink(DataFlow::Node sink, FlowState state) {
@@ -152,12 +171,12 @@ module ArrayAddressToDerefConfig implements DataFlow::StateConfigSig {
152171
predicate isAdditionalFlowStep(
153172
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
154173
) {
155-
exists(PointerArithmeticInstruction pai, Variable v |
156-
state1 = TArray(v) and
174+
exists(PointerArithmeticInstruction pai |
175+
state1 = TArray() and
157176
state2 = TOverflowArithmetic(pai) and
158177
pai.getLeft() = node1.asInstruction() and
159178
node2.asInstruction() = pai and
160-
pointerArithOverflow(pai, v, _, _, _)
179+
pointerArithOverflow(pai, _)
161180
)
162181
}
163182
}
@@ -168,11 +187,11 @@ from
168187
Variable v, ArrayAddressToDerefFlow::PathNode source, PointerArithmeticInstruction pai,
169188
ArrayAddressToDerefFlow::PathNode sink, Instruction deref, string operation, int delta
170189
where
171-
ArrayAddressToDerefFlow::flowPath(source, sink) and
190+
ArrayAddressToDerefFlow::flowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
172191
isInvalidPointerDerefSink2(sink.getNode(), deref, operation) and
173-
source.getState() = ArrayAddressToDerefConfig::TArray(v) and
174-
sink.getState() = ArrayAddressToDerefConfig::TOverflowArithmetic(pai) and
175-
pointerArithOverflow(pai, v, _, _, delta)
192+
pragma[only_bind_out](sink.getState()) = ArrayAddressToDerefConfig::TOverflowArithmetic(pai) and
193+
isSourceImpl(source.getNode(), v) and
194+
finalPointerArithOverflow(v, pai, delta)
176195
select pai, source, sink,
177196
"This pointer arithmetic may have an off-by-" + (delta + 1) +
178197
" error allowing it to overrun $@ at this $@.", v, v.getName(), deref, operation

cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ edges
1111
| test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... |
1212
| test.cpp:79:27:79:34 | buf | test.cpp:70:33:70:33 | p |
1313
| test.cpp:79:32:79:34 | buf | test.cpp:79:27:79:34 | buf |
14+
| test.cpp:85:34:85:36 | buf | test.cpp:87:5:87:31 | access to array |
15+
| test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array |
1416
| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array |
1517
| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... |
1618
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr |
@@ -38,6 +40,9 @@ nodes
3840
| test.cpp:77:32:77:34 | buf | semmle.label | buf |
3941
| test.cpp:79:27:79:34 | buf | semmle.label | buf |
4042
| test.cpp:79:32:79:34 | buf | semmle.label | buf |
43+
| test.cpp:85:34:85:36 | buf | semmle.label | buf |
44+
| test.cpp:87:5:87:31 | access to array | semmle.label | access to array |
45+
| test.cpp:88:5:88:27 | access to array | semmle.label | access to array |
4146
| test.cpp:128:9:128:11 | arr | semmle.label | arr |
4247
| test.cpp:128:9:128:14 | access to array | semmle.label | access to array |
4348
| test.cpp:134:25:134:27 | arr | semmle.label | arr |

0 commit comments

Comments
 (0)