Skip to content

Commit 930efc2

Browse files
committed
C++: Fix up uses of GuardCondition.
1 parent d50a266 commit 930efc2

File tree

26 files changed

+154
-122
lines changed

26 files changed

+154
-122
lines changed

cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/RangeAnalysis.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private predicate bestOperandBound(Operand op, Bound b, int delta, boolean upper
171171
private IRGuardCondition eqFlowCond(
172172
ValueNumber vn, Operand bound, int delta, boolean isEq, boolean testIsTrue
173173
) {
174-
result.comparesEq(vn.getAUse(), bound, delta, isEq, testIsTrue)
174+
result.comparesEq(vn, valueNumberOfOperand(bound), delta, isEq, testIsTrue)
175175
}
176176

177177
/**
@@ -207,7 +207,7 @@ private IRGuardCondition boundFlowCond(
207207
ValueNumber vn, NonPhiOperand bound, int delta, boolean upper, boolean testIsTrue
208208
) {
209209
exists(int d |
210-
result.comparesLt(vn.getAUse(), bound, d, upper, testIsTrue) and
210+
result.comparesLt(vn, valueNumberOfOperand(bound), d, upper, testIsTrue) and
211211
// `comparesLt` provides bounds of the form `x < y + k` or `x >= y + k`, but we need
212212
// `x <= y + k` so we strengthen here. `testIsTrue` has the same semantics in `comparesLt` as
213213
// it does here, so we don't need to account for it.

cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/SignAnalysis.qll

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -297,16 +297,17 @@ private predicate unknownSign(Instruction i) {
297297
private predicate lowerBound(
298298
IRGuardCondition comp, Operand lowerbound, Operand bounded, boolean isStrict
299299
) {
300-
exists(int adjustment, Operand compared |
301-
valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and
300+
exists(int adjustment, ValueNumber compared |
301+
valueNumberOfOperand(bounded) = compared and
302302
(
303303
isStrict = true and
304304
adjustment = 0
305305
or
306306
isStrict = false and
307307
adjustment = 1
308308
) and
309-
comp.ensuresLt(lowerbound, compared, adjustment, bounded.getUse().getBlock(), true)
309+
comp.ensuresLt(valueNumberOfOperand(lowerbound), compared, adjustment,
310+
bounded.getUse().getBlock(), true)
310311
)
311312
}
312313

@@ -317,16 +318,17 @@ private predicate lowerBound(
317318
private predicate upperBound(
318319
IRGuardCondition comp, Operand upperbound, Operand bounded, boolean isStrict
319320
) {
320-
exists(int adjustment, Operand compared |
321-
valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and
321+
exists(int adjustment, ValueNumber compared |
322+
valueNumberOfOperand(bounded) = compared and
322323
(
323324
isStrict = true and
324325
adjustment = 0
325326
or
326327
isStrict = false and
327328
adjustment = 1
328329
) and
329-
comp.ensuresLt(compared, upperbound, adjustment, bounded.getUse().getBlock(), true)
330+
comp.ensuresLt(compared, valueNumberOfOperand(upperbound), adjustment,
331+
bounded.getUse().getBlock(), true)
330332
)
331333
}
332334

@@ -338,9 +340,9 @@ private predicate upperBound(
338340
* - `isEq = false` : `bounded != eqbound`
339341
*/
340342
private predicate eqBound(IRGuardCondition guard, Operand eqbound, Operand bounded, boolean isEq) {
341-
exists(Operand compared |
342-
valueNumberOfOperand(bounded) = valueNumberOfOperand(compared) and
343-
guard.ensuresEq(compared, eqbound, 0, bounded.getUse().getBlock(), isEq)
343+
exists(ValueNumber compared |
344+
valueNumberOfOperand(bounded) = compared and
345+
guard.ensuresEq(compared, valueNumberOfOperand(eqbound), 0, bounded.getUse().getBlock(), isEq)
344346
)
345347
}
346348

cpp/ql/lib/semmle/code/cpp/controlflow/Guards.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import semmle.code.cpp.controlflow.BasicBlocks
88
import semmle.code.cpp.controlflow.SSA
99
import semmle.code.cpp.controlflow.Dominance
1010
import IRGuards
11+
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1112

1213
/** An `SsaDefinition` with an additional predicate `isLt`. */
1314
class GuardedSsa extends SsaDefinition {
1415
/** Holds if this `SsaDefinition` is guarded such that `this(var) < gt + k` is `testIsTrue` in `block`. */
15-
predicate isLt(StackVariable var, Expr gt, int k, BasicBlock block, boolean testIsTrue) {
16-
exists(Expr luse, GuardCondition test | this.getAUse(var) = luse |
16+
predicate isLt(StackVariable var, GVN gt, int k, BasicBlock block, boolean testIsTrue) {
17+
exists(GVN luse, GuardCondition test | this.getAUse(var) = luse.getAnExpr() |
1718
test.ensuresLt(luse, gt, k, block, testIsTrue)
1819
)
1920
}

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,12 +1238,16 @@ module IsUnreachableInCall {
12381238
}
12391239

12401240
pragma[nomagic]
1241-
private predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
1241+
private predicate ensuresEq(
1242+
ValueNumber left, ValueNumber right, int k, IRBlock block, boolean areEqual
1243+
) {
12421244
any(G::IRGuardCondition guard).ensuresEq(left, right, k, block, areEqual)
12431245
}
12441246

12451247
pragma[nomagic]
1246-
private predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
1248+
private predicate ensuresLt(
1249+
ValueNumber left, ValueNumber right, int k, IRBlock block, boolean areEqual
1250+
) {
12471251
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
12481252
}
12491253

@@ -1256,13 +1260,13 @@ module IsUnreachableInCall {
12561260
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
12571261
exists(
12581262
InstructionDirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
1259-
IntegerConstantInstruction constant, int k, Operand left, Operand right, int argval
1263+
IntegerConstantInstruction constant, int k, ValueNumber left, ValueNumber right, int argval
12601264
|
12611265
// arg flows into `paramNode`
12621266
DataFlowImplCommon::viableParamArg(call, pragma[only_bind_into](paramNode),
12631267
pragma[only_bind_into](arg)) and
1264-
left = constant.getAUse() and
1265-
right = valueNumber(paramNode.getInstruction()).getAUse() and
1268+
left.getAnInstruction() = constant and
1269+
right.getAnInstruction() = paramNode.getInstruction() and
12661270
argval = arg.getValue()
12671271
|
12681272
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`

cpp/ql/lib/semmle/code/cpp/ir/internal/ASTValueNumbering.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ class GVN extends TValueNumber {
109109

110110
/** Gets an expression that has this GVN. */
111111
Expr getAConvertedExpr() { result = this.getAnInstruction().getConvertedResultExpression() }
112+
113+
pragma[nomagic]
114+
Function getEnclosingFunction() { result = this.getAnExpr().getEnclosingFunction() }
112115
}
113116

114117
/** Gets the global value number of expression `e`. */

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,10 @@ module SemanticExprConfig {
240240
Expr getGuardAsExpr(Guard guard) { result = getSemanticExpr(guard) }
241241

242242
predicate equalityGuard(Guard guard, Expr e1, Expr e2, boolean polarity) {
243-
exists(IR::Instruction left, IR::Instruction right |
244-
getSemanticExpr(left) = e1 and
245-
getSemanticExpr(right) = e2 and
246-
guard.comparesEq(left.getAUse(), right.getAUse(), 0, true, polarity)
243+
exists(ValueNumber left, ValueNumber right |
244+
getSemanticExpr(left.getAnInstruction()) = e1 and
245+
getSemanticExpr(right.getAnInstruction()) = e2 and
246+
guard.comparesEq(left, right, 0, true, polarity)
247247
)
248248
}
249249

cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/AllocationToInvalidPointer.qll

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,21 +134,23 @@ private module SizeBarrier {
134134
* Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`.
135135
*/
136136
additional predicate isSink(
137-
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
137+
ValueNumber small, ValueNumber large, IRGuardCondition g, int k, boolean testIsTrue
138138
) {
139139
// The sink is any "large" side of a relational comparison. i.e., the `large` expression
140140
// in a guard such as `small <= large + k`.
141-
g.comparesLt(small.asOperand(), large.asOperand(), k + 1, true, testIsTrue)
141+
g.comparesLt(small, large, k + 1, true, testIsTrue)
142142
}
143143

144-
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
144+
predicate isSink(DataFlow::Node sink) {
145+
isSink(_, valueNumberOfOperand(sink.asOperand()), _, _, _)
146+
}
145147
}
146148

147149
module SizeBarrierFlow = DataFlow::Global<SizeBarrierConfig>;
148150

149-
private int getASizeAddend(DataFlow::Node node) {
151+
private int getASizeAddend(ValueNumber node) {
150152
exists(DataFlow::Node source |
151-
SizeBarrierFlow::flow(source, node) and
153+
SizeBarrierFlow::flow(source, DataFlow::operandNode(node.getAUse())) and
152154
hasSize(_, source, result)
153155
)
154156
}
@@ -157,10 +159,10 @@ private module SizeBarrier {
157159
* Holds if `small <= large + k` holds if `g` evaluates to `edge`.
158160
*/
159161
private predicate operandGuardChecks(
160-
IRGuardCondition g, Operand small, DataFlow::Node large, int k, boolean edge
162+
IRGuardCondition g, ValueNumber small, ValueNumber large, int k, boolean edge
161163
) {
162-
SizeBarrierFlow::flowTo(large) and
163-
SizeBarrierConfig::isSink(DataFlow::operandNode(small), large, g, k, edge)
164+
SizeBarrierFlow::flowTo(DataFlow::operandNode(large.getAUse())) and
165+
SizeBarrierConfig::isSink(small, large, g, k, edge)
164166
}
165167

166168
/**
@@ -170,15 +172,15 @@ private module SizeBarrier {
170172
*/
171173
Instruction getABarrierInstruction0(int delta, int k) {
172174
exists(
173-
IRGuardCondition g, ValueNumber value, Operand small, boolean edge, DataFlow::Node large
175+
IRGuardCondition g, ValueNumber value, ValueNumber small, boolean edge, ValueNumber large
174176
|
175177
// We know:
176178
// 1. result <= value + delta (by `bounded`)
177179
// 2. value <= large + k (by `operandGuardChecks`).
178180
// So:
179181
// result <= value + delta (by 1.)
180182
// <= large + k + delta (by 2.)
181-
small = value.getAUse() and
183+
small = value and
182184
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](small), large,
183185
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
184186
bounded(result, value.getAnInstruction(), delta) and

cpp/ql/lib/semmle/code/cpp/security/InvalidPointerDereference/InvalidPointerToDereference.qll

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,15 @@ private module InvalidPointerToDerefBarrier {
101101
predicate isSource(DataFlow::Node source) { isSource(source, _) }
102102

103103
additional predicate isSink(
104-
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
104+
ValueNumber small, ValueNumber large, IRGuardCondition g, int k, boolean testIsTrue
105105
) {
106106
// The sink is any "large" side of a relational comparison.
107-
g.comparesLt(small.asOperand(), large.asOperand(), k, true, testIsTrue)
107+
g.comparesLt(small, large, k, true, testIsTrue)
108108
}
109109

110-
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
110+
predicate isSink(DataFlow::Node sink) {
111+
isSink(_, valueNumberOfOperand(sink.asOperand()), _, _, _)
112+
}
111113

112114
int fieldFlowBranchLimit() { result = invalidPointerToDereferenceFieldFlowBranchLimit() }
113115
}
@@ -123,11 +125,11 @@ private module InvalidPointerToDerefBarrier {
123125
private predicate operandGuardChecks(
124126
PointerArithmeticInstruction pai, IRGuardCondition g, Operand small, int k, boolean edge
125127
) {
126-
exists(DataFlow::Node source, DataFlow::Node nSmall, DataFlow::Node nLarge |
127-
nSmall.asOperand() = small and
128+
exists(DataFlow::Node source, ValueNumber nSmall, DataFlow::Node nLarge |
129+
nSmall.getAUse() = small and
128130
BarrierConfig::isSource(source, pai) and
129131
BarrierFlow::flow(source, nLarge) and
130-
BarrierConfig::isSink(nSmall, nLarge, g, k, edge)
132+
BarrierConfig::isSink(nSmall, valueNumberOfOperand(nLarge.asOperand()), g, k, edge)
131133
)
132134
}
133135

cpp/ql/lib/semmle/code/cpp/security/Overflow.qll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import semmle.code.cpp.controlflow.Dominance
88
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
99
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
1010
import semmle.code.cpp.controlflow.Guards
11+
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1112

1213
/**
1314
* Holds if the value of `use` is guarded using `abs`.
1415
*/
1516
predicate guardedAbs(Operation e, Expr use) {
1617
exists(FunctionCall fc | fc.getTarget().getName() = ["abs", "labs", "llabs", "imaxabs"] |
1718
fc.getArgument(0).getAChild*() = use and
18-
exists(GuardCondition c | c.ensuresLt(fc, _, _, e.getBasicBlock(), true))
19+
exists(GuardCondition c | c.ensuresLt(globalValueNumber(fc), _, _, e.getBasicBlock(), true))
1920
)
2021
}
2122

@@ -25,7 +26,7 @@ predicate guardedAbs(Operation e, Expr use) {
2526
*/
2627
pragma[nomagic]
2728
predicate guardedLesser(Operation e, Expr use) {
28-
exists(GuardCondition c | c.ensuresLt(use, _, _, e.getBasicBlock(), true))
29+
exists(GuardCondition c | c.ensuresLt(globalValueNumber(use), _, _, e.getBasicBlock(), true))
2930
or
3031
guardedAbs(e, use)
3132
}
@@ -36,7 +37,7 @@ predicate guardedLesser(Operation e, Expr use) {
3637
*/
3738
pragma[nomagic]
3839
predicate guardedGreater(Operation e, Expr use) {
39-
exists(GuardCondition c | c.ensuresLt(use, _, _, e.getBasicBlock(), false))
40+
exists(GuardCondition c | c.ensuresLt(globalValueNumber(use), _, _, e.getBasicBlock(), false))
4041
or
4142
guardedAbs(e, use)
4243
}

cpp/ql/src/Critical/MissingCheckScanf.ql

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,10 @@ predicate hasNonGuardedAccess(
157157
|
158158
not exists(GuardCondition guard |
159159
// call == k and k >= minGuard so call >= minGuard
160-
guard
161-
.ensuresEq(globalValueNumber(call).getAnExpr(), any(int k | minGuard <= k),
162-
e.getBasicBlock(), true)
160+
guard.ensuresEq(globalValueNumber(call), any(int k | minGuard <= k), e.getBasicBlock(), true)
163161
or
164162
// call >= k and k >= minGuard so call >= minGuard
165-
guard
166-
.ensuresLt(globalValueNumber(call).getAnExpr(), any(int k | minGuard <= k),
167-
e.getBasicBlock(), false)
163+
guard.ensuresLt(globalValueNumber(call), any(int k | minGuard <= k), e.getBasicBlock(), false)
168164
)
169165
)
170166
}

0 commit comments

Comments
 (0)