Skip to content

Commit e0f0b0a

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

24 files changed

+141
-111
lines changed

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
}

cpp/ql/src/Critical/OverflowDestination.ql

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import cpp
1717
import semmle.code.cpp.ir.dataflow.TaintTracking
1818
import semmle.code.cpp.controlflow.IRGuards
1919
import semmle.code.cpp.security.FlowSources
20+
import semmle.code.cpp.ir.ValueNumbering
2021
import OverflowDestination::PathGraph
2122

2223
/**
@@ -61,7 +62,9 @@ predicate hasUpperBoundsCheck(Variable var) {
6162
)
6263
}
6364

64-
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
65+
predicate nodeIsBarrierEqualityCandidate(
66+
DataFlow::Node node, ValueNumber access, Variable checkedVar
67+
) {
6568
readsVariable(node.asInstruction(), checkedVar) and
6669
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
6770
}
@@ -77,8 +80,8 @@ module OverflowDestinationConfig implements DataFlow::ConfigSig {
7780
hasUpperBoundsCheck(checkedVar)
7881
)
7982
or
80-
exists(Variable checkedVar, Operand access |
81-
readsVariable(access.getDef(), checkedVar) and
83+
exists(Variable checkedVar, ValueNumber access |
84+
readsVariable(access.getAnInstruction(), checkedVar) and
8285
nodeIsBarrierEqualityCandidate(node, access, checkedVar)
8386
)
8487
}

cpp/ql/src/Critical/ScanfChecks.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ private predicate exprInBooleanContext(Expr e) {
77
exists(IRGuardCondition gc |
88
exists(Instruction i |
99
i.getUnconvertedResultExpression() = e and
10-
gc.comparesEq(valueNumber(i).getAUse(), 0, _, _)
10+
gc.comparesEq(valueNumber(i), 0, _, _)
1111
)
1212
or
1313
gc.getUnconvertedResultExpression() = e
@@ -38,15 +38,15 @@ private string getEofValue() {
3838
private predicate checkedForEof(ScanfFunctionCall call) {
3939
exists(IRGuardCondition gc |
4040
exists(Instruction i | i.getUnconvertedResultExpression() = call |
41-
exists(int val | gc.comparesEq(valueNumber(i).getAUse(), val, _, _) |
41+
exists(int val | gc.comparesEq(valueNumber(i), val, _, _) |
4242
// call == EOF
4343
val = getEofValue().toInt()
4444
or
4545
// call == [any positive number]
4646
val > 0
4747
)
4848
or
49-
exists(int val | gc.comparesLt(valueNumber(i).getAUse(), val, true, _) |
49+
exists(int val | gc.comparesLt(valueNumber(i), val, true, _) |
5050
// call < [any non-negative number] (EOF is guaranteed to be negative)
5151
val >= 0
5252
)

0 commit comments

Comments
 (0)