Skip to content

Commit 73ae613

Browse files
committed
Shared: Many tweaks to Guards.
1 parent c212d0a commit 73ae613

File tree

1 file changed

+83
-10
lines changed

1 file changed

+83
-10
lines changed

shared/controlflow/codeql/controlflow/Guards.qll

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
234234
/** Holds if this value represents `null`. */
235235
predicate isNullValue() { this = TValue(TValueNull(), true) }
236236

237+
/** Holds if this value represents `null` or non-`null` as indicated by `isNull`. */
238+
predicate isNullness(boolean isNull) { this = TValue(TValueNull(), isNull) }
239+
237240
/** Gets the integer that this value represents, if any. */
238241
int asIntValue() { this = TValue(TValueInt(result), true) }
239242

@@ -320,17 +323,19 @@ module Make<LocationSig Location, InputSig<Location> Input> {
320323
)
321324
)
322325
or
323-
exists(Case c |
326+
exceptionBranchPoint(bb1, bb2, _) and v = TException(false)
327+
or
328+
exceptionBranchPoint(bb1, _, bb2) and v = TException(true)
329+
}
330+
331+
private predicate caseBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue v, Expr switchExpr) {
332+
exists(Case c | switchExpr = c.getSwitchExpr() |
324333
v = TCaseMatch(c, true) and
325334
c.matchEdge(bb1, bb2)
326335
or
327336
v = TCaseMatch(c, false) and
328337
c.nonMatchEdge(bb1, bb2)
329338
)
330-
or
331-
exceptionBranchPoint(bb1, bb2, _) and v = TException(false)
332-
or
333-
exceptionBranchPoint(bb1, _, bb2) and v = TException(true)
334339
}
335340

336341
pragma[nomagic]
@@ -362,12 +367,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
362367
*/
363368
final class PreGuard extends ExprFinal {
364369
/**
365-
* Holds if this guard is the last node in `bb1` and that its successor is
366-
* `bb2` exactly when evaluating to `v`.
370+
* Holds if this guard evaluating to `v` corresponds to taking the edge
371+
* from `bb1` to `bb2`. For ordinary conditional branching this guard is
372+
* the last node in `bb1`, but for switch case matching it is the switch
373+
* expression, which may either be in `bb1` or an earlier basic block.
367374
*/
368375
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue v) {
369376
bb1.getLastNode() = this.getControlFlowNode() and
370377
branchEdge(bb1, bb2, v)
378+
or
379+
caseBranchEdge(bb1, bb2, v, this)
371380
}
372381

373382
/**
@@ -457,6 +466,12 @@ module Make<LocationSig Location, InputSig<Location> Input> {
457466
BasicBlock getBasicBlock();
458467

459468
Expr getARead();
469+
470+
/** Gets a textual representation of this SSA definition. */
471+
string toString();
472+
473+
/** Gets the location of this SSA definition. */
474+
Location getLocation();
460475
}
461476

462477
class SsaWriteDefinition extends SsaDefinition {
@@ -549,6 +564,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
549564
other.getARead() = guard and
550565
eqtest.directlyControls(guard.getBasicBlock(), branch)
551566
)
567+
or
568+
// An expression `x = ...` can be considered as a read of `x`.
569+
guard.(IdExpr).getEqualChildExpr() = def.(SsaWriteDefinition).getDefinition()
552570
}
553571

554572
private predicate valueStep(Expr e1, Expr e2) {
@@ -649,7 +667,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
649667
)
650668
}
651669

652-
private predicate impliesStep(Guard g1, GuardValue v1, Guard g2, GuardValue v2) {
670+
private predicate impliesStep1(Guard g1, GuardValue v1, Guard g2, GuardValue v2) {
653671
baseImpliesStep(g1, v1, g2, v2)
654672
or
655673
exists(SsaDefinition def, Expr e |
@@ -689,7 +707,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
689707
or
690708
baseSsaValueCheck(def, ssaVal, g0, v0)
691709
|
692-
impliesStep(g, v, g0, v0)
710+
impliesStep1(g, v, g0, v0)
693711
)
694712
}
695713

@@ -712,6 +730,16 @@ module Make<LocationSig Location, InputSig<Location> Input> {
712730
)
713731
}
714732

733+
private predicate impliesStep2(Guard g1, GuardValue v1, Guard g2, GuardValue v2) {
734+
impliesStep1(g1, v1, g2, v2)
735+
or
736+
exists(Expr nonnull |
737+
exprHasValue(nonnull, v2) and
738+
eqtestHasOperands(g1, g2, nonnull, v1.asBooleanValue()) and
739+
v2 = TValue(TValueNull(), false)
740+
)
741+
}
742+
715743
bindingset[g1, v1]
716744
pragma[inline_late]
717745
private predicate unboundImpliesStep(Guard g1, GuardValue v1, Guard g2, GuardValue v2) {
@@ -779,7 +807,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
779807
or
780808
exists(Guard g0, GuardValue v0 |
781809
guardControls(g0, v0, tgtGuard, tgtVal) and
782-
impliesStep(g0, v0, guard, v)
810+
impliesStep2(g0, v0, guard, v)
783811
)
784812
or
785813
exists(Guard g0, GuardValue v0 |
@@ -816,6 +844,27 @@ module Make<LocationSig Location, InputSig<Location> Input> {
816844
}
817845
}
818846

847+
private predicate booleanGuard(Guard guard, GuardValue val) {
848+
exists(guard) and exists(val.asBooleanValue())
849+
}
850+
851+
private module BooleanImplies = ImpliesTC<booleanGuard/2>;
852+
853+
/** INTERNAL: Don't use. */
854+
predicate boolImplies(Guard g1, GuardValue v1, Guard g2, GuardValue v2) {
855+
BooleanImplies::guardControls(g2, v2, g1, v1) and
856+
g2 != g1
857+
}
858+
859+
/**
860+
* Holds if `guard` evaluating to `v` implies that `e` is guaranteed to be
861+
* null if `isNull` is true, and non-null if `isNull` is false.
862+
*/
863+
predicate nullGuard(Guard guard, GuardValue v, Expr e, boolean isNull) {
864+
impliesStep2(guard, v, e, TValue(TValueNull(), isNull)) or
865+
additionalImpliesStep(guard, v, e, TValue(TValueNull(), isNull))
866+
}
867+
819868
private predicate hasAValueBranchEdge(Guard guard, GuardValue v) {
820869
guard.hasValueBranchEdge(_, _, v)
821870
}
@@ -831,6 +880,30 @@ module Make<LocationSig Location, InputSig<Location> Input> {
831880
)
832881
}
833882

883+
/**
884+
* Holds if `def` evaluating to `v` controls the control-flow branch
885+
* edge from `bb1` to `bb2`. That is, following the edge from `bb1` to
886+
* `bb2` implies that `def` evaluated to `v`.
887+
*/
888+
predicate ssaControlsBranchEdge(SsaDefinition def, BasicBlock bb1, BasicBlock bb2, GuardValue v) {
889+
exists(Guard g0, GuardValue v0 |
890+
g0.hasValueBranchEdge(bb1, bb2, v0) and
891+
BranchImplies::ssaControls(def, v, g0, v0)
892+
)
893+
}
894+
895+
/**
896+
* Holds if `def` evaluating to `v` controls the basic block `bb`.
897+
* That is, execution of `bb` implies that `def` evaluated to `v`.
898+
*/
899+
predicate ssaControls(SsaDefinition def, BasicBlock bb, GuardValue v) {
900+
exists(BasicBlock guard, BasicBlock succ |
901+
ssaControlsBranchEdge(def, guard, succ, v) and
902+
dominatingEdge(guard, succ) and
903+
succ.dominates(bb)
904+
)
905+
}
906+
834907
signature module CustomGuardInputSig {
835908
class ParameterPosition {
836909
/** Gets a textual representation of this element. */

0 commit comments

Comments
 (0)