Skip to content

Commit c212d0a

Browse files
committed
Shared: Improve shared guards lib.
1 parent 16c5b57 commit c212d0a

File tree

1 file changed

+77
-45
lines changed

1 file changed

+77
-45
lines changed

shared/controlflow/codeql/controlflow/Guards.qll

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
299299
v = TValue(TValueConstant(c.asConstantValue()), true)
300300
}
301301

302-
private predicate exprHasValue(Expr e, GuardValue v) {
303-
constantHasValue(e, v)
304-
or
305-
e instanceof NonNullExpr and v = TValue(TValueNull(), false)
306-
}
307-
308302
private predicate exceptionBranchPoint(BasicBlock bb1, BasicBlock normalSucc, BasicBlock excSucc) {
309303
exists(SuccessorType norm, ExceptionSuccessor exc |
310304
bb1.getASuccessor(norm) = normalSucc and
@@ -426,30 +420,6 @@ module Make<LocationSig Location, InputSig<Location> Input> {
426420
branch = false and result = cond.getElse()
427421
}
428422

429-
bindingset[g1, v1]
430-
pragma[inline_late]
431-
private predicate unboundBaseImpliesStep(PreGuard g1, GuardValue v1, PreGuard g2, GuardValue v2) {
432-
g1.(IdExpr).getEqualChildExpr() = g2 and v1 = v2 and not v1 instanceof TException
433-
or
434-
exists(ConditionalExpr cond, boolean branch, Expr e, GuardValue ev |
435-
cond = g1 and
436-
e = getBranchExpr(cond, branch) and
437-
exprHasValue(e, ev) and
438-
disjointValues(v1, ev)
439-
|
440-
// g1 === g2 ? e : ...;
441-
// g1 === g2 ? ... : e;
442-
g2 = cond.getCondition() and
443-
v2 = TValue(TValueTrue(), branch.booleanNot())
444-
or
445-
// g1 === ... ? g2 : e
446-
// g1 === ... ? e : g2
447-
g2 = getBranchExpr(cond, branch.booleanNot()) and
448-
v2 = v1 and
449-
not exprHasValue(g2, v2) // disregard trivial guard
450-
)
451-
}
452-
453423
private predicate baseImpliesStep(PreGuard g1, GuardValue v1, PreGuard g2, GuardValue v2) {
454424
g1.(AndExpr).getAnOperand() = g2 and v1 = TValue(TValueTrue(), true) and v2 = v1
455425
or
@@ -532,15 +502,17 @@ module Make<LocationSig Location, InputSig<Location> Input> {
532502
private import LogicInput
533503

534504
private predicate guardControlsPhiBranch(
535-
Guard guard, GuardValue v, SsaPhiNode phi, Expr input, BasicBlock bbInput, BasicBlock bbPhi
505+
Guard guard, GuardValue v, SsaPhiNode phi, SsaDefinition inp
536506
) {
537-
exists(SsaWriteDefinition inp |
538-
phi.hasInputFromBlock(inp, bbInput) and
507+
exists(BasicBlock bbPhi |
508+
phi.hasInputFromBlock(inp, _) and
539509
phi.getBasicBlock() = bbPhi and
540-
inp.getDefinition() = input and
541-
guard.directlyValueControls(bbInput, v) and
542510
guard.getBasicBlock().strictlyDominates(bbPhi) and
543-
not guard.directlyValueControls(bbPhi, _)
511+
not guard.directlyValueControls(bbPhi, _) and
512+
forex(BasicBlock bbInput | phi.hasInputFromBlock(inp, bbInput) |
513+
guard.directlyValueControls(bbInput, v) or
514+
guard.hasValueBranchEdge(bbInput, bbPhi, v)
515+
)
544516
)
545517
}
546518

@@ -552,13 +524,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
552524
* This makes `phi` similar to the conditional `phi = guard==v ? input : ...`.
553525
*/
554526
private predicate guardDeterminesPhiInput(Guard guard, GuardValue v, SsaPhiNode phi, Expr input) {
555-
exists(GuardValue dv, BasicBlock bbInput, BasicBlock bbPhi |
556-
guardControlsPhiBranch(guard, v, phi, input, bbInput, bbPhi) and
527+
exists(GuardValue dv, SsaWriteDefinition inp |
528+
guardControlsPhiBranch(guard, v, phi, inp) and
529+
inp.getDefinition() = input and
557530
dv = v.getDualValue() and
558-
forall(BasicBlock other | phi.hasInputFromBlock(_, other) and other != bbInput |
559-
guard.directlyValueControls(other, dv)
560-
or
561-
guard.hasValueBranchEdge(other, bbPhi, dv)
531+
forall(SsaDefinition other | phi.hasInputFromBlock(other, _) and other != inp |
532+
guardControlsPhiBranch(guard, dv, phi, other)
562533
)
563534
)
564535
}
@@ -702,14 +673,67 @@ module Make<LocationSig Location, InputSig<Location> Input> {
702673
or
703674
exists(boolean isNull |
704675
additionalNullCheck(g1, v1, g2, isNull) and
705-
v2 = TValue(TValueNull(), isNull)
676+
v2 = TValue(TValueNull(), isNull) and
677+
not (g2 instanceof NonNullExpr and isNull = false) // disregard trivial guard
678+
)
679+
}
680+
681+
/**
682+
* Holds if `g` evaluating to `v` implies that `def` evaluates to `ssaVal`.
683+
* The included set of implications is somewhat restricted to avoid a
684+
* recursive dependency on `exprHasValue`.
685+
*/
686+
private predicate baseSsaValueCheck(SsaDefinition def, GuardValue ssaVal, Guard g, GuardValue v) {
687+
exists(Guard g0, GuardValue v0 |
688+
guardReadsSsaVar(g0, def) and v0 = ssaVal
689+
or
690+
baseSsaValueCheck(def, ssaVal, g0, v0)
691+
|
692+
impliesStep(g, v, g0, v0)
693+
)
694+
}
695+
696+
private predicate exprHasValue(Expr e, GuardValue v) {
697+
constantHasValue(e, v)
698+
or
699+
e instanceof NonNullExpr and v = TValue(TValueNull(), false)
700+
or
701+
exprHasValue(e.(IdExpr).getEqualChildExpr(), v)
702+
or
703+
exists(SsaDefinition def, Guard g, GuardValue gv |
704+
e = def.getARead() and
705+
g.directlyValueControls(e.getBasicBlock(), gv) and
706+
baseSsaValueCheck(def, v, g, gv)
707+
)
708+
or
709+
exists(SsaWriteDefinition def |
710+
exprHasValue(def.getDefinition(), v) and
711+
e = def.getARead()
706712
)
707713
}
708714

709715
bindingset[g1, v1]
710716
pragma[inline_late]
711717
private predicate unboundImpliesStep(Guard g1, GuardValue v1, Guard g2, GuardValue v2) {
712-
unboundBaseImpliesStep(g1, v1, g2, v2)
718+
g1.(IdExpr).getEqualChildExpr() = g2 and v1 = v2 and not v1 instanceof TException
719+
or
720+
exists(ConditionalExpr cond, boolean branch, Expr e, GuardValue ev |
721+
cond = g1 and
722+
e = getBranchExpr(cond, branch) and
723+
exprHasValue(e, ev) and
724+
disjointValues(v1, ev)
725+
|
726+
// g1 === g2 ? e : ...;
727+
// g1 === g2 ? ... : e;
728+
g2 = cond.getCondition() and
729+
v2 = TValue(TValueTrue(), branch.booleanNot())
730+
or
731+
// g1 === ... ? g2 : e
732+
// g1 === ... ? e : g2
733+
g2 = getBranchExpr(cond, branch.booleanNot()) and
734+
v2 = v1 and
735+
not exprHasValue(g2, v2) // disregard trivial guard
736+
)
713737
}
714738

715739
bindingset[def1, v1]
@@ -742,7 +766,11 @@ module Make<LocationSig Location, InputSig<Location> Input> {
742766
* Calculates the transitive closure of all the guard implication steps
743767
* starting from a given set of base cases.
744768
*/
745-
private module ImpliesTC<baseGuardValueSig/2 baseGuardValue> {
769+
module ImpliesTC<baseGuardValueSig/2 baseGuardValue> {
770+
/**
771+
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
772+
* evaluates to `v`.
773+
*/
746774
pragma[nomagic]
747775
predicate guardControls(Guard guard, GuardValue v, Guard tgtGuard, GuardValue tgtVal) {
748776
baseGuardValue(tgtGuard, tgtVal) and
@@ -770,6 +798,10 @@ module Make<LocationSig Location, InputSig<Location> Input> {
770798
)
771799
}
772800

801+
/**
802+
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `def`
803+
* evaluates to `v`.
804+
*/
773805
pragma[nomagic]
774806
predicate ssaControls(SsaDefinition def, GuardValue v, Guard tgtGuard, GuardValue tgtVal) {
775807
exists(Guard g0 |

0 commit comments

Comments
 (0)