mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
SSA: Distinguish between has and controls branch edge.
This commit is contained in:
@@ -1903,6 +1903,10 @@ module IteratorFlow {
|
|||||||
predicate allowFlowIntoUncertainDef(IteratorSsa::UncertainWriteDefinition def) { any() }
|
predicate allowFlowIntoUncertainDef(IteratorSsa::UncertainWriteDefinition def) { any() }
|
||||||
|
|
||||||
class Guard extends Void {
|
class Guard extends Void {
|
||||||
|
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
predicate controlsBranchEdge(
|
predicate controlsBranchEdge(
|
||||||
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch
|
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -991,13 +991,17 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
|
|||||||
class Guard instanceof IRGuards::IRGuardCondition {
|
class Guard instanceof IRGuards::IRGuardCondition {
|
||||||
string toString() { result = super.toString() }
|
string toString() { result = super.toString() }
|
||||||
|
|
||||||
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
exists(EdgeKind kind |
|
exists(EdgeKind kind |
|
||||||
super.getBlock() = bb1 and
|
super.getBlock() = bb1 and
|
||||||
kind = getConditionalEdge(branch) and
|
kind = getConditionalEdge(branch) and
|
||||||
bb1.getSuccessor(kind) = bb2
|
bb1.getSuccessor(kind) = bb2
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
|
this.hasBranchEdge(bb1, bb2, branch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
|
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
|
||||||
|
|||||||
@@ -1044,17 +1044,25 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
|||||||
|
|
||||||
class Guard extends Guards::Guard {
|
class Guard extends Guards::Guard {
|
||||||
/**
|
/**
|
||||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
* Holds if the evaluation of this guard to `branch` corresponds to the edge
|
||||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
* from `bb1` to `bb2`.
|
||||||
* guard to `branch`.
|
|
||||||
*/
|
*/
|
||||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
predicate hasBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||||
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
|
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
|
||||||
this.getAControlFlowNode() = bb1.getLastNode() and
|
this.getAControlFlowNode() = bb1.getLastNode() and
|
||||||
bb2 = bb1.getASuccessorByType(s) and
|
bb2 = bb1.getASuccessorByType(s) and
|
||||||
s.getValue() = branch
|
s.getValue() = branch
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||||
|
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||||
|
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||||
|
*/
|
||||||
|
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||||
|
this.hasBranchEdge(bb1, bb2, branch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
||||||
|
|||||||
@@ -272,6 +272,15 @@ class Guard extends ExprParent {
|
|||||||
preconditionControls(this, controlled, branch)
|
preconditionControls(this, controlled, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||||
|
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||||
|
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||||
|
*/
|
||||||
|
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||||
|
guardControlsBranchEdge_v3(this, bb1, bb2, branch)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this guard evaluating to `branch` directly or indirectly controls
|
* Holds if this guard evaluating to `branch` directly or indirectly controls
|
||||||
* the block `controlled`. That is, the evaluation of `controlled` is
|
* the block `controlled`. That is, the evaluation of `controlled` is
|
||||||
@@ -351,6 +360,18 @@ private predicate guardControls_v3(Guard guard, BasicBlock controlled, boolean b
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma[nomagic]
|
||||||
|
private predicate guardControlsBranchEdge_v3(
|
||||||
|
Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch
|
||||||
|
) {
|
||||||
|
guard.hasBranchEdge(bb1, bb2, branch)
|
||||||
|
or
|
||||||
|
exists(Guard g, boolean b |
|
||||||
|
guardControlsBranchEdge_v3(g, bb1, bb2, b) and
|
||||||
|
implies_v3(g, b, guard, branch)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
|
private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
|
||||||
exists(EqualityTest eqtest |
|
exists(EqualityTest eqtest |
|
||||||
eqtest = g and
|
eqtest = g and
|
||||||
|
|||||||
@@ -654,16 +654,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
|||||||
def instanceof SsaUncertainImplicitUpdate
|
def instanceof SsaUncertainImplicitUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
class Guard extends Guards::Guard {
|
class Guard = Guards::Guard;
|
||||||
/**
|
|
||||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
|
||||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
|
||||||
* guard to `branch`.
|
|
||||||
*/
|
|
||||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
|
||||||
super.hasBranchEdge(bb1, bb2, branch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Holds if the guard `guard` directly controls block `bb` upon evaluating to `branch`. */
|
/** Holds if the guard `guard` directly controls block `bb` upon evaluating to `branch`. */
|
||||||
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) {
|
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) {
|
||||||
|
|||||||
@@ -75,11 +75,10 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
|
|||||||
Guard() { this = any(js::ConditionGuardNode g).getTest() }
|
Guard() { this = any(js::ConditionGuardNode g).getTest() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
* Holds if the evaluation of this guard to `branch` corresponds to the edge
|
||||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
* from `bb1` to `bb2`.
|
||||||
* guard to `branch`.
|
|
||||||
*/
|
*/
|
||||||
predicate controlsBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
|
predicate hasBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
|
||||||
exists(js::ConditionGuardNode g |
|
exists(js::ConditionGuardNode g |
|
||||||
g.getTest() = this and
|
g.getTest() = this and
|
||||||
bb1 = this.getBasicBlock() and
|
bb1 = this.getBasicBlock() and
|
||||||
@@ -87,6 +86,15 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
|
|||||||
branch = g.getOutcome()
|
branch = g.getOutcome()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||||
|
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||||
|
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||||
|
*/
|
||||||
|
predicate controlsBranchEdge(js::BasicBlock bb1, js::BasicBlock bb2, boolean branch) {
|
||||||
|
this.hasBranchEdge(bb1, bb2, branch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
|
|||||||
@@ -484,17 +484,25 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
|||||||
|
|
||||||
class Guard extends Cfg::CfgNodes::AstCfgNode {
|
class Guard extends Cfg::CfgNodes::AstCfgNode {
|
||||||
/**
|
/**
|
||||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
* Holds if the evaluation of this guard to `branch` corresponds to the edge
|
||||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
* from `bb1` to `bb2`.
|
||||||
* guard to `branch`.
|
|
||||||
*/
|
*/
|
||||||
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
exists(Cfg::SuccessorTypes::ConditionalSuccessor s |
|
exists(Cfg::SuccessorTypes::ConditionalSuccessor s |
|
||||||
this.getBasicBlock() = bb1 and
|
this.getBasicBlock() = bb1 and
|
||||||
bb2 = bb1.getASuccessor(s) and
|
bb2 = bb1.getASuccessor(s) and
|
||||||
s.getValue() = branch
|
s.getValue() = branch
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||||
|
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||||
|
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||||
|
*/
|
||||||
|
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
|
this.hasBranchEdge(bb1, bb2, branch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
||||||
|
|||||||
@@ -363,17 +363,25 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
|
|||||||
|
|
||||||
class Guard extends CfgNodes::AstCfgNode {
|
class Guard extends CfgNodes::AstCfgNode {
|
||||||
/**
|
/**
|
||||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
* Holds if the evaluation of this guard to `branch` corresponds to the edge
|
||||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
* from `bb1` to `bb2`.
|
||||||
* guard to `branch`.
|
|
||||||
*/
|
*/
|
||||||
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
predicate hasBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
exists(Cfg::ConditionalSuccessor s |
|
exists(Cfg::ConditionalSuccessor s |
|
||||||
this = bb1.getANode() and
|
this = bb1.getANode() and
|
||||||
bb2 = bb1.getASuccessor(s) and
|
bb2 = bb1.getASuccessor(s) and
|
||||||
s.getValue() = branch
|
s.getValue() = branch
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||||
|
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||||
|
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||||
|
*/
|
||||||
|
predicate controlsBranchEdge(SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, boolean branch) {
|
||||||
|
this.hasBranchEdge(bb1, bb2, branch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
|
||||||
|
|||||||
@@ -732,6 +732,8 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Guard extends Void {
|
class Guard extends Void {
|
||||||
|
predicate hasBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) { none() }
|
||||||
|
|
||||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) { none() }
|
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1570,9 +1570,15 @@ module Make<LocationSig Location, InputSig<Location> Input> {
|
|||||||
string toString();
|
string toString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the control flow branching from `bb1` is dependent on this guard,
|
* Holds if the evaluation of this guard to `branch` corresponds to the edge
|
||||||
* and that the edge from `bb1` to `bb2` corresponds to the evaluation of this
|
* from `bb1` to `bb2`.
|
||||||
* guard to `branch`.
|
*/
|
||||||
|
predicate hasBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this guard evaluating to `branch` controls the control-flow
|
||||||
|
* branch edge from `bb1` to `bb2`. That is, following the edge from
|
||||||
|
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
|
||||||
*/
|
*/
|
||||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch);
|
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch);
|
||||||
}
|
}
|
||||||
@@ -1667,7 +1673,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
|
|||||||
(
|
(
|
||||||
// The input node is relevant either if it sits directly on a branch
|
// The input node is relevant either if it sits directly on a branch
|
||||||
// edge for a guard,
|
// edge for a guard,
|
||||||
exists(DfInput::Guard g | g.controlsBranchEdge(input, phi.getBasicBlock(), _))
|
exists(DfInput::Guard g | g.hasBranchEdge(input, phi.getBasicBlock(), _))
|
||||||
or
|
or
|
||||||
// or if the unique predecessor is not an equivalent substitute in
|
// or if the unique predecessor is not an equivalent substitute in
|
||||||
// terms of being controlled by the same guards.
|
// terms of being controlled by the same guards.
|
||||||
|
|||||||
Reference in New Issue
Block a user