Skip to content

Commit 417e79c

Browse files
authored
Merge pull request #20382 from MathiasVP/simplify-ssl-result-not-checked
C++: Simplify `cpp/certificate-not-checked`
2 parents 4b9d102 + 702d6d8 commit 417e79c

File tree

2 files changed

+106
-24
lines changed

2 files changed

+106
-24
lines changed

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

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,20 @@ abstract private class GuardConditionImpl extends Expr {
7272
*/
7373
abstract predicate valueControls(BasicBlock controlled, AbstractValue v);
7474

75+
/**
76+
* Holds if the control-flow edge `(pred, succ)` may be taken only if
77+
* the value of this condition is `v`.
78+
*/
79+
abstract predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v);
80+
81+
/**
82+
* Holds if the control-flow edge `(pred, succ)` may be taken only if
83+
* this the value of this condition is `testIsTrue`.
84+
*/
85+
final predicate controlsEdge(BasicBlock pred, BasicBlock succ, boolean testIsTrue) {
86+
this.valueControlsEdge(pred, succ, any(BooleanValue bv | bv.getValue() = testIsTrue))
87+
}
88+
7589
/**
7690
* Holds if this condition controls `controlled`, meaning that `controlled` is only
7791
* entered if the value of this condition is `testIsTrue`.
@@ -175,6 +189,58 @@ abstract private class GuardConditionImpl extends Expr {
175189
*/
176190
pragma[inline]
177191
abstract predicate ensuresEq(Expr e, int k, BasicBlock block, boolean areEqual);
192+
193+
/**
194+
* Holds if (determined by this guard) `left == right + k` must be `areEqual` on the edge from
195+
* `pred` to `succ`. If `areEqual = false` then this implies `left != right + k`.
196+
*/
197+
pragma[inline]
198+
final predicate ensuresEqEdge(
199+
Expr left, Expr right, int k, BasicBlock pred, BasicBlock succ, boolean areEqual
200+
) {
201+
exists(boolean testIsTrue |
202+
this.comparesEq(left, right, k, areEqual, testIsTrue) and
203+
this.controlsEdge(pred, succ, testIsTrue)
204+
)
205+
}
206+
207+
/**
208+
* Holds if (determined by this guard) `e == k` must be `areEqual` on the edge from
209+
* `pred` to `succ`. If `areEqual = false` then this implies `e != k`.
210+
*/
211+
pragma[inline]
212+
final predicate ensuresEqEdge(Expr e, int k, BasicBlock pred, BasicBlock succ, boolean areEqual) {
213+
exists(AbstractValue v |
214+
this.comparesEq(e, k, areEqual, v) and
215+
this.valueControlsEdge(pred, succ, v)
216+
)
217+
}
218+
219+
/**
220+
* Holds if (determined by this guard) `left < right + k` must be `isLessThan` on the edge from
221+
* `pred` to `succ`. If `isLessThan = false` then this implies `left >= right + k`.
222+
*/
223+
pragma[inline]
224+
final predicate ensuresLtEdge(
225+
Expr left, Expr right, int k, BasicBlock pred, BasicBlock succ, boolean isLessThan
226+
) {
227+
exists(boolean testIsTrue |
228+
this.comparesLt(left, right, k, isLessThan, testIsTrue) and
229+
this.controlsEdge(pred, succ, testIsTrue)
230+
)
231+
}
232+
233+
/**
234+
* Holds if (determined by this guard) `e < k` must be `isLessThan` on the edge from
235+
* `pred` to `succ`. If `isLessThan = false` then this implies `e >= k`.
236+
*/
237+
pragma[inline]
238+
final predicate ensuresLtEdge(Expr e, int k, BasicBlock pred, BasicBlock succ, boolean isLessThan) {
239+
exists(AbstractValue v |
240+
this.comparesLt(e, k, isLessThan, v) and
241+
this.valueControlsEdge(pred, succ, v)
242+
)
243+
}
178244
}
179245

180246
final class GuardCondition = GuardConditionImpl;
@@ -187,6 +253,16 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardConditionImpl
187253
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
188254
}
189255

256+
override predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v) {
257+
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
258+
this = binop and
259+
lhs = binop.getLeftOperand() and
260+
rhs = binop.getRightOperand() and
261+
lhs.valueControlsEdge(pred, succ, v) and
262+
rhs.valueControlsEdge(pred, succ, v)
263+
)
264+
}
265+
190266
override predicate valueControls(BasicBlock controlled, AbstractValue v) {
191267
exists(BinaryLogicalOperation binop, GuardCondition lhs, GuardCondition rhs |
192268
this = binop and
@@ -274,6 +350,25 @@ private predicate controlsBlock(IRGuardCondition ir, BasicBlock controlled, Abst
274350
)
275351
}
276352

353+
/**
354+
* Holds if `ir` controls the `(pred, succ)` edge, meaning that the edge
355+
* `(pred, succ)` is only taken if the value of this condition is `v`. This
356+
* helper predicate does not necessarily hold for binary logical operations
357+
* like `&&` and `||`.
358+
* See the detailed explanation on predicate `controlsEdge`.
359+
*/
360+
private predicate controlsEdge(
361+
IRGuardCondition ir, BasicBlock pred, BasicBlock succ, AbstractValue v
362+
) {
363+
exists(IRBlock irPred, IRBlock irSucc |
364+
ir.valueControlsEdge(irPred, irSucc, v) and
365+
nonExcludedIRAndBasicBlock(irPred, pred) and
366+
nonExcludedIRAndBasicBlock(irSucc, succ) and
367+
not isUnreachedBlock(irPred) and
368+
not isUnreachedBlock(irSucc)
369+
)
370+
}
371+
277372
private class GuardConditionFromNotExpr extends GuardConditionImpl {
278373
IRGuardCondition ir;
279374

@@ -295,6 +390,10 @@ private class GuardConditionFromNotExpr extends GuardConditionImpl {
295390
controlsBlock(ir, controlled, v.getDualValue())
296391
}
297392

393+
override predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v) {
394+
controlsEdge(ir, pred, succ, v.getDualValue())
395+
}
396+
298397
pragma[inline]
299398
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
300399
exists(Instruction li, Instruction ri |
@@ -383,6 +482,10 @@ private class GuardConditionFromIR extends GuardConditionImpl {
383482
controlsBlock(ir, controlled, v)
384483
}
385484

485+
override predicate valueControlsEdge(BasicBlock pred, BasicBlock succ, AbstractValue v) {
486+
controlsEdge(ir, pred, succ, v)
487+
}
488+
386489
pragma[inline]
387490
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
388491
exists(Instruction li, Instruction ri |

cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,9 @@ predicate resultIsChecked(SslGetPeerCertificateCall getCertCall, ControlFlowNode
5555
predicate certIsZero(
5656
SslGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
5757
) {
58-
exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
59-
exists(GuardCondition guard, Expr zero |
60-
zero.getValue().toInt() = 0 and
61-
node1 = guard and
62-
(
63-
// if (cert == zero) {
64-
guard.comparesEq(cert, zero, 0, true, true) and
65-
node2 = guard.getATrueSuccessor()
66-
or
67-
// if (cert != zero) { }
68-
guard.comparesEq(cert, zero, 0, false, true) and
69-
node2 = guard.getAFalseSuccessor()
70-
)
71-
)
72-
or
73-
(
74-
// if (cert) { }
75-
node1 = cert
76-
or
77-
// if (!cert) {
78-
node1.(NotExpr).getAChild() = cert
79-
) and
80-
node2 = node1.getASuccessor() and
81-
not cert.(GuardCondition).controls(node2, true) // cert may be false
58+
exists(Expr cert |
59+
cert = globalValueNumber(getCertCall).getAnExpr() and
60+
node1.(GuardCondition).ensuresEqEdge(cert, 0, _, node2.getBasicBlock(), true)
8261
)
8362
}
8463

0 commit comments

Comments
 (0)