Languages: Adapt to api changes.

This commit is contained in:
Anders Schack-Mulligen
2025-08-19 10:34:06 +02:00
parent e53b22dfa7
commit f459ddc40a
34 changed files with 454 additions and 368 deletions

View File

@@ -1880,9 +1880,7 @@ module IteratorFlow {
}
}
private module SsaInput implements SsaImpl::InputSig<Location> {
import Ssa::InputSigCommon
private module SsaInput implements SsaImpl::InputSig<Location, IRCfg::BasicBlock> {
class SourceVariable = IteratorFlow::SourceVariable;
/** A call to function that dereferences an iterator. */
@@ -1960,7 +1958,7 @@ module IteratorFlow {
* Holds if `(bb, i)` contains a write to an iterator that may have been obtained
* by calling `begin` (or related functions) on the variable `v`.
*/
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(IRCfg::BasicBlock bb, int i, SourceVariable v, boolean certain) {
certain = false and
exists(GetsIteratorCall beginCall, Instruction writeToDeref, IRBlock bbQual, int iQual |
isIteratorStoreInstruction(beginCall, writeToDeref) and
@@ -1971,12 +1969,12 @@ module IteratorFlow {
}
/** Holds if `(bb, i)` reads the container variable `v`. */
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(IRCfg::BasicBlock bb, int i, SourceVariable v, boolean certain) {
Ssa::variableRead(bb, i, v, certain)
}
}
private module IteratorSsa = SsaImpl::Make<Location, SsaInput>;
private module IteratorSsa = SsaImpl::Make<Location, IRCfg, SsaInput>;
private module DataFlowIntegrationInput implements IteratorSsa::DataFlowIntegrationInputSig {
private import codeql.util.Void
@@ -1989,7 +1987,7 @@ module IteratorFlow {
)
}
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { bb.getInstruction(i) = this }
predicate hasCfgNode(IRCfg::BasicBlock bb, int i) { bb.getInstruction(i) = this }
}
predicate ssaDefHasSource(IteratorSsa::WriteDefinition def) { none() }
@@ -1999,20 +1997,16 @@ module IteratorFlow {
class GuardValue = Void;
class Guard extends Void {
predicate hasValueBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue val
) {
predicate hasValueBranchEdge(IRCfg::BasicBlock bb1, IRCfg::BasicBlock bb2, GuardValue val) {
none()
}
predicate valueControlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue val
) {
predicate valueControlsBranchEdge(IRCfg::BasicBlock bb1, IRCfg::BasicBlock bb2, GuardValue val) {
none()
}
}
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, GuardValue val) {
predicate guardDirectlyControlsBlock(Guard guard, IRCfg::BasicBlock bb, GuardValue val) {
none()
}

View File

@@ -891,15 +891,14 @@ private predicate baseSourceVariableIsGlobal(
)
}
private module SsaInput implements Ssa::InputSig<Location> {
import InputSigCommon
private module SsaInput implements Ssa::InputSig<Location, IRCfg::BasicBlock> {
import SourceVariables
/**
* Holds if the `i`'th write in block `bb` writes to the variable `v`.
* `certain` is `true` if the write is guaranteed to overwrite the entire variable.
*/
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(IRCfg::BasicBlock bb, int i, SourceVariable v, boolean certain) {
DataFlowImplCommon::forceCachingInSameStage() and
(
exists(DefImpl def | def.hasIndexInBlock(v, bb, i) |
@@ -917,7 +916,7 @@ private module SsaInput implements Ssa::InputSig<Location> {
* Holds if the `i`'th read in block `bb` reads to the variable `v`.
* `certain` is `true` if the read is guaranteed. For C++, this is always the case.
*/
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(IRCfg::BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(UseImpl use | use.hasIndexInBlock(bb, i, v) |
if use.isCertain() then certain = true else certain = false
)
@@ -965,7 +964,7 @@ class GlobalDef extends Definition {
GlobalLikeVariable getVariable() { result = impl.getVariable() }
}
private module SsaImpl = Ssa::Make<Location, SsaInput>;
private module SsaImpl = Ssa::Make<Location, IRCfg, SsaInput>;
private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationInputSig {
private import codeql.util.Boolean
@@ -978,7 +977,7 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
)
}
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { bb.getInstruction(i) = this }
predicate hasCfgNode(IRCfg::BasicBlock bb, int i) { bb.getInstruction(i) = this }
}
Expr getARead(SsaImpl::Definition def) {
@@ -1006,9 +1005,7 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
class Guard instanceof IRGuards::IRGuardCondition {
string toString() { result = super.toString() }
predicate hasValueBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue branch
) {
predicate hasValueBranchEdge(IRCfg::BasicBlock bb1, IRCfg::BasicBlock bb2, GuardValue branch) {
exists(EdgeKind kind |
super.getBlock() = bb1 and
kind = getConditionalEdge(branch) and
@@ -1017,13 +1014,13 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
}
predicate valueControlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue branch
IRCfg::BasicBlock bb1, IRCfg::BasicBlock bb2, GuardValue branch
) {
this.hasValueBranchEdge(bb1, bb2, branch)
}
}
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, GuardValue branch) {
predicate guardDirectlyControlsBlock(Guard guard, IRCfg::BasicBlock bb, GuardValue branch) {
guard.(IRGuards::IRGuardCondition).controls(bb, branch)
}

View File

@@ -768,23 +768,3 @@ private module Cached {
}
import Cached
/**
* Inputs to the shared SSA library's parameterized module that is shared
* between the SSA pruning stage, and the final SSA stage.
*/
module InputSigCommon {
class BasicBlock extends IRBlock {
ControlFlowNode getNode(int i) { result = this.getInstruction(i) }
int length() { result = this.getInstructionCount() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result.immediatelyDominates(this) }
predicate inDominanceFrontier(BasicBlock df) { super.dominanceFrontier() = df }
}
class ControlFlowNode = Instruction;
}

View File

@@ -7,6 +7,7 @@ import Instruction
private import internal.IRBlockImports as Imports
import Imports::EdgeKind
private import Cached
private import codeql.controlflow.BasicBlock as BB
/**
* Holds if `block` is a block in `func` and `sortOverride`, `sortKey1`, and `sortKey2` are the
@@ -263,6 +264,45 @@ private predicate isEntryBlock(TIRBlock block) {
block = MkIRBlock(any(EnterFunctionInstruction enter))
}
module IRCfg implements BB::CfgSig<Language::Location> {
class ControlFlowNode = Instruction;
class SuccessorType = EdgeKind;
class BasicBlock extends IRBlock {
ControlFlowNode getNode(int i) { result = this.getInstruction(i) }
ControlFlowNode getLastNode() { result = super.getLastInstruction() }
int length() { result = this.getInstructionCount() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getSuccessor(t) }
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }
predicate dominates(BasicBlock bb) { super.dominates(bb) }
BasicBlock getImmediateDominator() { result.immediatelyDominates(this) }
predicate inDominanceFrontier(BasicBlock df) { super.dominanceFrontier() = df }
predicate strictlyPostDominates(BasicBlock bb) { super.strictlyPostDominates(bb) }
predicate postDominates(BasicBlock bb) { super.postDominates(bb) }
}
pragma[nomagic]
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
bb1.getASuccessor() = bb2 and
bb1 = bb2.getImmediateDominator() and
forall(BasicBlock pred | pred = bb2.getAPredecessor() and pred != bb1 | bb2.dominates(pred))
}
predicate entryBlock(BasicBlock bb) { isEntryBlock(bb) }
}
cached
private module Cached {
cached

View File

@@ -29,7 +29,7 @@ predicate bbSuccInconsistency(ControlFlowElement pred, ControlFlowElement succ)
succBB.getFirstNode() = succ.getAControlFlowNode()
) and
not exists(PreBasicBlock predBB, PreBasicBlock succBB |
predBB.getLastElement() = pred and
predBB.getLastNode() = pred and
succBB = predBB.getASuccessor() and
succBB.getFirstElement() = succ
)
@@ -41,7 +41,7 @@ predicate bbIntraSuccInconsistency(ControlFlowElement pred, ControlFlowElement s
succ.getAControlFlowNode() = bb.getNode(i + 1)
) and
not exists(PreBasicBlock bb |
bb.getLastElement() = pred and
bb.getLastNode() = pred and
bb.getASuccessor().getFirstElement() = succ
) and
not exists(PreBasicBlock bb, int i |

View File

@@ -6,6 +6,7 @@ import csharp
private import ControlFlow::SuccessorTypes
private import semmle.code.csharp.controlflow.internal.ControlFlowGraphImpl as CfgImpl
private import CfgImpl::BasicBlocks as BasicBlocksImpl
private import codeql.controlflow.BasicBlock as BB
/**
* A basic block, that is, a maximal straight-line sequence of control flow nodes
@@ -13,7 +14,12 @@ private import CfgImpl::BasicBlocks as BasicBlocksImpl
*/
final class BasicBlock extends BasicBlocksImpl::BasicBlock {
/** Gets an immediate successor of this basic block of a given type, if any. */
BasicBlock getASuccessorByType(ControlFlow::SuccessorType t) { result = this.getASuccessor(t) }
BasicBlock getASuccessor(ControlFlow::SuccessorType t) { result = super.getASuccessor(t) }
/** DEPRECATED: Use `getASuccessor` instead. */
deprecated BasicBlock getASuccessorByType(ControlFlow::SuccessorType t) {
result = this.getASuccessor(t)
}
/** Gets an immediate predecessor of this basic block of a given type, if any. */
BasicBlock getAPredecessorByType(ControlFlow::SuccessorType t) {
@@ -332,3 +338,19 @@ final class ConditionBlock extends BasicBlock, BasicBlocksImpl::ConditionBasicBl
super.edgeDominates(controlled, s)
}
}
private class BasicBlockAlias = BasicBlock;
module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlow::Node;
class SuccessorType = ControlFlow::SuccessorType;
class BasicBlock = BasicBlockAlias;
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
BasicBlocksImpl::dominatingEdge(bb1, bb2)
}
predicate entryBlock(BasicBlock bb) { bb instanceof EntryBasicBlock }
}

View File

@@ -90,7 +90,7 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
// all other nodes can use regular CFG dominance
this instanceof Impl::SplitAstNode and
cb.getLastNode() = this.getAControlFlowNode() and
succ = cb.getASuccessorByType(s)
succ = cb.getASuccessor(s)
}
pragma[noinline]

View File

@@ -999,7 +999,7 @@ module Internal {
pragma[nomagic]
private predicate preControlsDirect(Guard g, PreBasicBlocks::PreBasicBlock bb, AbstractValue v) {
exists(PreBasicBlocks::ConditionBlock cb, ConditionalSuccessor s | cb.controls(bb, s) |
v.branch(cb.getLastElement(), s, g)
v.branch(cb.getLastNode(), s, g)
)
}
@@ -1146,9 +1146,9 @@ module Internal {
/** Gets the successor block that is reached when guard `g` has abstract value `v`. */
private PreBasicBlocks::PreBasicBlock getConditionalSuccessor(Guard g, AbstractValue v) {
exists(PreBasicBlocks::ConditionBlock pred, ConditionalSuccessor s |
v.branch(pred.getLastElement(), s, g)
v.branch(pred.getLastNode(), s, g)
|
result = pred.getASuccessorByType(s)
result = pred.getASuccessor(s)
)
}

View File

@@ -13,6 +13,7 @@ import csharp
private import Completion
private import ControlFlowGraphImpl
private import semmle.code.csharp.controlflow.ControlFlowGraph::ControlFlow as Cfg
private import codeql.controlflow.BasicBlock as BB
private predicate startsBB(ControlFlowElement cfe) {
not succ(_, cfe, _) and
@@ -55,11 +56,15 @@ private predicate bbIDominates(PreBasicBlock dom, PreBasicBlock bb) =
class PreBasicBlock extends ControlFlowElement {
PreBasicBlock() { startsBB(this) }
PreBasicBlock getASuccessorByType(Cfg::SuccessorType t) {
succ(this.getLastElement(), result, any(Completion c | t = c.getAMatchingSuccessorType()))
PreBasicBlock getASuccessor(Cfg::SuccessorType t) {
succ(this.getLastNode(), result, any(Completion c | t = c.getAMatchingSuccessorType()))
}
PreBasicBlock getASuccessor() { result = this.getASuccessorByType(_) }
deprecated PreBasicBlock getASuccessorByType(Cfg::SuccessorType t) {
result = this.getASuccessor(t)
}
PreBasicBlock getASuccessor() { result = this.getASuccessor(_) }
PreBasicBlock getAPredecessor() { result.getASuccessor() = this }
@@ -71,7 +76,9 @@ class PreBasicBlock extends ControlFlowElement {
ControlFlowElement getFirstElement() { result = this }
ControlFlowElement getLastElement() { result = this.getNode(this.length() - 1) }
ControlFlowElement getLastNode() { result = this.getNode(this.length() - 1) }
deprecated ControlFlowElement getLastElement() { result = this.getLastNode() }
int length() { result = strictcount(this.getAnElement()) }
@@ -97,45 +104,72 @@ class PreBasicBlock extends ControlFlowElement {
not bbIDominates(this, df)
)
}
/** Unsupported. Do not use. */
predicate strictlyPostDominates(PreBasicBlock bb) { none() }
/** Unsupported. Do not use. */
predicate postDominates(PreBasicBlock bb) {
this.strictlyPostDominates(bb) or
this = bb
}
}
private Completion getConditionalCompletion(ConditionalCompletion cc) {
result.getInnerCompletion() = cc
}
pragma[nomagic]
private predicate conditionBlockImmediatelyControls(
ConditionBlock cond, PreBasicBlock succ, ConditionalCompletion cc
) {
exists(ControlFlowElement last, Completion c |
last = cond.getLastNode() and
c = getConditionalCompletion(cc) and
succ(last, succ, c) and
// In the pre-CFG, we need to account for case where one predecessor node has
// two edges to the same successor node. Assertion expressions are examples of
// such nodes.
not exists(Completion other |
succ(last, succ, other) and
other != c
) and
forall(PreBasicBlock pred | pred = succ.getAPredecessor() and pred != cond |
succ.dominates(pred)
)
)
}
class ConditionBlock extends PreBasicBlock {
ConditionBlock() {
exists(Completion c | c = getConditionalCompletion(_) |
succ(this.getLastElement(), _, c)
succ(this.getLastNode(), _, c)
or
scopeLast(_, this.getLastElement(), c)
)
}
pragma[nomagic]
private predicate immediatelyControls(PreBasicBlock succ, ConditionalCompletion cc) {
exists(ControlFlowElement last, Completion c |
last = this.getLastElement() and
c = getConditionalCompletion(cc) and
succ(last, succ, c) and
// In the pre-CFG, we need to account for case where one predecessor node has
// two edges to the same successor node. Assertion expressions are examples of
// such nodes.
not exists(Completion other |
succ(last, succ, other) and
other != c
) and
forall(PreBasicBlock pred | pred = succ.getAPredecessor() and pred != this |
succ.dominates(pred)
)
scopeLast(_, this.getLastNode(), c)
)
}
pragma[nomagic]
predicate controls(PreBasicBlock controlled, Cfg::SuccessorTypes::ConditionalSuccessor s) {
exists(PreBasicBlock succ, ConditionalCompletion c | this.immediatelyControls(succ, c) |
exists(PreBasicBlock succ, ConditionalCompletion c |
conditionBlockImmediatelyControls(this, succ, c)
|
succ.dominates(controlled) and
s = c.getAMatchingSuccessorType()
)
}
}
module PreCfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowElement;
class SuccessorType = Cfg::SuccessorType;
class BasicBlock = PreBasicBlock;
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
conditionBlockImmediatelyControls(bb1, bb2, _)
}
predicate entryBlock(BasicBlock bb) { entryBB(bb) }
}

View File

@@ -12,7 +12,7 @@ module PreSsa {
private import codeql.ssa.Ssa as SsaImplCommon
private predicate definitionAt(
AssignableDefinition def, SsaInput::BasicBlock bb, int i, SsaInput::SourceVariable v
AssignableDefinition def, PreBasicBlocks::PreBasicBlock bb, int i, SsaInput::SourceVariable v
) {
bb.getNode(i) = def.getExpr() and
v = def.getTarget() and
@@ -30,7 +30,9 @@ module PreSsa {
)
}
predicate implicitEntryDef(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v) {
predicate implicitEntryDef(
Callable c, PreBasicBlocks::PreBasicBlock bb, SsaInput::SourceVariable v
) {
c = v.getACallable() and
scopeFirst(c, bb) and
(
@@ -79,13 +81,9 @@ module PreSsa {
}
}
module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = PreBasicBlocks::PreBasicBlock;
class ControlFlowNode = ControlFlowElement;
private class ExitBasicBlock extends BasicBlock {
ExitBasicBlock() { scopeLast(_, this.getLastElement(), _) }
module SsaInput implements SsaImplCommon::InputSig<Location, PreBasicBlocks::PreBasicBlock> {
private class ExitBasicBlock extends PreBasicBlocks::PreBasicBlock {
ExitBasicBlock() { scopeLast(_, this.getLastNode(), _) }
}
pragma[noinline]
@@ -123,7 +121,9 @@ module PreSsa {
Callable getACallable() { result = c }
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(
PreBasicBlocks::PreBasicBlock bb, int i, SourceVariable v, boolean certain
) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.getTargetAccess().isRefArgument() then certain = false else certain = true
@@ -134,7 +134,9 @@ module PreSsa {
certain = true
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(
PreBasicBlocks::PreBasicBlock bb, int i, SourceVariable v, boolean certain
) {
exists(AssignableRead read |
read = bb.getNode(i) and
read.getTarget() = v and
@@ -151,25 +153,25 @@ module PreSsa {
}
}
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
private module SsaImpl = SsaImplCommon::Make<Location, PreBasicBlocks::PreCfg, SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {
exists(SsaInput::BasicBlock bb, int i |
exists(PreBasicBlocks::PreBasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(_, this, bb, i) and
result = bb.getNode(i)
)
}
final AssignableDefinition getDefinition() {
exists(SsaInput::BasicBlock bb, int i, SsaInput::SourceVariable v |
exists(PreBasicBlocks::PreBasicBlock bb, int i, SsaInput::SourceVariable v |
this.definesAt(v, bb, i) and
definitionAt(result, bb, i, v)
)
}
final AssignableRead getAFirstRead() {
exists(SsaInput::BasicBlock bb, int i |
exists(PreBasicBlocks::PreBasicBlock bb, int i |
SsaImpl::firstUse(this, bb, i, true) and
result = bb.getNode(i)
)
@@ -185,14 +187,14 @@ module PreSsa {
not result instanceof PhiNode
}
final predicate isLiveAtEndOfBlock(SsaInput::BasicBlock bb) {
final predicate isLiveAtEndOfBlock(PreBasicBlocks::PreBasicBlock bb) {
SsaImpl::ssaDefReachesEndOfBlock(bb, this, _)
}
override Location getLocation() {
result = this.getDefinition().getLocation()
or
exists(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v |
exists(Callable c, PreBasicBlocks::PreBasicBlock bb, SsaInput::SourceVariable v |
this.definesAt(v, bb, -1) and
implicitEntryDef(c, bb, v) and
result = c.getLocation()
@@ -207,7 +209,7 @@ module PreSsa {
}
predicate adjacentReadPairSameVar(AssignableRead read1, AssignableRead read2) {
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
exists(PreBasicBlocks::PreBasicBlock bb1, int i1, PreBasicBlocks::PreBasicBlock bb2, int i2 |
read1 = bb1.getNode(i1) and
SsaImpl::adjacentUseUse(bb1, i1, bb2, i2, _, true) and
read2 = bb2.getNode(i2)

View File

@@ -899,7 +899,7 @@ module BooleanSplitting {
/** Holds if control flow element `cfe` starts a split of this kind. */
predicate startsSplit(AstNode cfe) {
this.correlatesConditions(any(ConditionBlock cb | cb.getLastElement() = cfe), _, _)
this.correlatesConditions(any(ConditionBlock cb | cb.getLastNode() = cfe), _, _)
}
/**
@@ -941,7 +941,7 @@ module BooleanSplitting {
/**
* Holds if condition `cb` is a read of the SSA variable in this split.
*/
private predicate defCondition(ConditionBlock cb) { cb.getLastElement() = def.getARead() }
private predicate defCondition(ConditionBlock cb) { cb.getLastNode() = def.getARead() }
/**
* Holds if condition `cb` is a read of the SSA variable in this split,
@@ -950,7 +950,7 @@ module BooleanSplitting {
*/
private predicate defConditionReachableFromRead(ConditionBlock cb, AssignableRead read) {
this.defCondition(cb) and
read = cb.getLastElement()
read = cb.getLastNode()
or
exists(AssignableRead mid | this.defConditionReachableFromRead(cb, mid) |
PreSsa::adjacentReadPairSameVar(read, mid) and
@@ -970,9 +970,9 @@ module BooleanSplitting {
override predicate correlatesConditions(ConditionBlock cb1, ConditionBlock cb2, boolean inverted) {
this.firstDefCondition(cb1) and
exists(AssignableRead read1, AssignableRead read2 |
read1 = cb1.getLastElement() and
read1 = cb1.getLastNode() and
PreSsa::adjacentReadPairSameVar+(read1, read2) and
read2 = cb2.getLastElement() and
read2 = cb2.getLastNode() and
inverted = false
)
}
@@ -1088,7 +1088,7 @@ module BooleanSplitting {
*/
private predicate appliesToBlock(PreBasicBlock bb, Completion c) {
this.appliesTo(bb) and
exists(AstNode last | last = bb.getLastElement() |
exists(AstNode last | last = bb.getLastNode() |
(succ(last, _, c) or scopeLast(_, last, c)) and
// Respect the value recorded in this split for all correlated conditions
forall(boolean inverted | bb = this.getACorrelatedCondition(inverted) |
@@ -1102,7 +1102,7 @@ module BooleanSplitting {
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
exists(PreBasicBlock bb | this.appliesToBlock(bb, c) |
pred = bb.getLastElement() and
pred = bb.getLastNode() and
succ(pred, succ, c) and
// Exit this split if we can no longer reach a correlated condition
not super.getSubKind().canReachCorrelatedCondition(succ)
@@ -1111,7 +1111,7 @@ module BooleanSplitting {
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
exists(PreBasicBlock bb | this.appliesToBlock(bb, c) |
last = bb.getLastElement() and
last = bb.getLastNode() and
scopeLast(scope, last, c)
)
}
@@ -1121,7 +1121,7 @@ module BooleanSplitting {
pred = bb.getAnElement() and
this.appliesSucc(pred, succ, c) and
(
pred = bb.getLastElement()
pred = bb.getLastNode()
implies
(
// We must still be able to reach a correlated condition to stay in this split

View File

@@ -297,7 +297,7 @@ private predicate defNullImpliesStep(
not exists(SuccessorTypes::ConditionalSuccessor s, NullValue nv |
bb1.getLastNode() = getANullCheck(def1, s, nv).getAControlFlowNode()
|
bb2 = bb1.getASuccessorByType(s) and
bb2 = bb1.getASuccessor(s) and
nv.isNonNull()
)
}

View File

@@ -5,6 +5,7 @@ import csharp
*/
module BaseSsa {
private import AssignableDefinitions
private import semmle.code.csharp.controlflow.BasicBlocks as BasicBlocks
private import codeql.ssa.Ssa as SsaImplCommon
/**
@@ -42,16 +43,12 @@ module BaseSsa {
)
}
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private module SsaInput implements SsaImplCommon::InputSig<Location, ControlFlow::BasicBlock> {
private import semmle.code.csharp.controlflow.internal.PreSsa
class BasicBlock = ControlFlow::BasicBlock;
class ControlFlowNode = ControlFlow::Node;
class SourceVariable = PreSsa::SimpleLocalScopeVariable;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(ControlFlow::BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableDefinition def |
definitionAt(def, bb, i, v) and
if def.isCertain() then certain = true else certain = false
@@ -62,7 +59,7 @@ module BaseSsa {
certain = true
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(ControlFlow::BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignableRead read |
read.getAControlFlowNode() = bb.getNode(i) and
read.getTarget() = v and
@@ -71,7 +68,7 @@ module BaseSsa {
}
}
private module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
private module SsaImpl = SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput>;
class Definition extends SsaImpl::Definition {
final AssignableRead getARead() {
@@ -108,7 +105,7 @@ module BaseSsa {
override Location getLocation() {
result = this.getDefinition().getLocation()
or
exists(Callable c, SsaInput::BasicBlock bb, SsaInput::SourceVariable v |
exists(Callable c, ControlFlow::BasicBlock bb, SsaInput::SourceVariable v |
this.definesAt(v, bb, -1) and
implicitEntryDef(c, bb, v) and
result = c.getLocation()

View File

@@ -264,6 +264,7 @@ predicate hasNodePath(ControlFlowReachabilityConfiguration conf, ExprNode n1, No
/** Provides logic related to captured variables. */
module VariableCapture {
private import codeql.dataflow.VariableCapture as Shared
private import semmle.code.csharp.controlflow.BasicBlocks as BasicBlocks
private predicate closureFlowStep(ControlFlow::Nodes::ExprNode e1, ControlFlow::Nodes::ExprNode e2) {
e1 = LocalFlow::getALastEvalNode(e2)
@@ -275,24 +276,15 @@ module VariableCapture {
)
}
private module CaptureInput implements Shared::InputSig<Location> {
private module CaptureInput implements Shared::InputSig<Location, BasicBlocks::BasicBlock> {
private import csharp as Cs
private import semmle.code.csharp.controlflow.ControlFlowGraph as Cfg
private import semmle.code.csharp.controlflow.BasicBlocks as BasicBlocks
private import TaintTrackingPrivate as TaintTrackingPrivate
class BasicBlock extends BasicBlocks::BasicBlock {
Callable getEnclosingCallable() { result = super.getCallable() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
Callable basicBlockGetEnclosingCallable(BasicBlocks::BasicBlock bb) {
result = bb.getCallable()
}
class ControlFlowNode = Cfg::ControlFlow::Node;
private predicate thisAccess(ControlFlow::Node cfn, InstanceCallable c) {
ThisFlow::thisAccessExpr(cfn.getAstNode()) and
cfn.getEnclosingCallable().getEnclosingCallable*() = c
@@ -359,7 +351,7 @@ module VariableCapture {
}
class Expr extends ControlFlow::Node {
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) { this = bb.getNode(i) }
}
class VariableWrite extends Expr {
@@ -411,7 +403,7 @@ module VariableCapture {
class ClosureExpr = CaptureInput::ClosureExpr;
module Flow = Shared::Flow<Location, CaptureInput>;
module Flow = Shared::Flow<Location, BasicBlocks::Cfg, CaptureInput>;
private Flow::ClosureNode asClosureNode(Node n) {
result = n.(CaptureNode).getSynthesizedCaptureNode()

View File

@@ -6,13 +6,10 @@ import csharp
private import codeql.ssa.Ssa as SsaImplCommon
private import AssignableDefinitions
private import semmle.code.csharp.controlflow.internal.PreSsa
private import semmle.code.csharp.controlflow.BasicBlocks as BasicBlocks
private import semmle.code.csharp.controlflow.Guards as Guards
private module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = ControlFlow::BasicBlock;
class ControlFlowNode = ControlFlow::Node;
private module SsaInput implements SsaImplCommon::InputSig<Location, ControlFlow::BasicBlock> {
class SourceVariable = Ssa::SourceVariable;
/**
@@ -21,7 +18,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
*
* This includes implicit writes via calls.
*/
predicate variableWrite(BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
predicate variableWrite(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableWriteDirect(bb, i, v, certain)
or
variableWriteQualifier(bb, i, v, certain)
@@ -35,7 +32,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
*
* This includes implicit reads via calls.
*/
predicate variableRead(BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
predicate variableRead(ControlFlow::BasicBlock bb, int i, Ssa::SourceVariable v, boolean certain) {
variableReadActual(bb, i, v) and
certain = true
or
@@ -44,7 +41,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
}
}
import SsaImplCommon::Make<Location, SsaInput> as Impl
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
class Definition = Impl::Definition;
@@ -725,7 +722,7 @@ private predicate variableReadPseudo(ControlFlow::BasicBlock bb, int i, Ssa::Sou
pragma[noinline]
deprecated private predicate adjacentDefRead(
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2,
SsaInput::SourceVariable v
) {
Impl::adjacentDefRead(def, bb1, i1, bb2, i2) and
@@ -733,8 +730,8 @@ deprecated private predicate adjacentDefRead(
}
deprecated private predicate adjacentDefReachesRead(
Definition def, SsaInput::SourceVariable v, SsaInput::BasicBlock bb1, int i1,
SsaInput::BasicBlock bb2, int i2
Definition def, SsaInput::SourceVariable v, ControlFlow::BasicBlock bb1, int i1,
ControlFlow::BasicBlock bb2, int i2
) {
adjacentDefRead(def, bb1, i1, bb2, i2, v) and
(
@@ -743,7 +740,7 @@ deprecated private predicate adjacentDefReachesRead(
SsaInput::variableRead(bb1, i1, v, true)
)
or
exists(SsaInput::BasicBlock bb3, int i3 |
exists(ControlFlow::BasicBlock bb3, int i3 |
adjacentDefReachesRead(def, v, bb1, i1, bb3, i3) and
SsaInput::variableRead(bb3, i3, _, false) and
Impl::adjacentDefRead(def, bb3, i3, bb2, i2)
@@ -751,7 +748,7 @@ deprecated private predicate adjacentDefReachesRead(
}
deprecated private predicate adjacentDefReachesUncertainRead(
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
Definition def, ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2
) {
exists(SsaInput::SourceVariable v |
adjacentDefReachesRead(def, v, bb1, i1, bb2, i2) and
@@ -762,12 +759,12 @@ deprecated private predicate adjacentDefReachesUncertainRead(
/** Same as `lastRefRedef`, but skips uncertain reads. */
pragma[nomagic]
deprecated private predicate lastRefSkipUncertainReads(
Definition def, SsaInput::BasicBlock bb, int i
Definition def, ControlFlow::BasicBlock bb, int i
) {
Impl::lastRef(def, bb, i) and
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
or
exists(SsaInput::BasicBlock bb0, int i0 |
exists(ControlFlow::BasicBlock bb0, int i0 |
Impl::lastRef(def, bb0, i0) and
adjacentDefReachesUncertainRead(def, bb, i, bb0, i0)
)
@@ -1050,7 +1047,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue branch) {
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
this.getAControlFlowNode() = bb1.getLastNode() and
bb2 = bb1.getASuccessorByType(s) and
bb2 = bb1.getASuccessor(s) and
s.getValue() = branch
)
}

View File

@@ -104,6 +104,10 @@ class BasicBlock extends BbImpl::BasicBlock {
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
predicate strictlyPostDominates(BasicBlock bb) { super.strictlyPostDominates(bb) }
predicate postDominates(BasicBlock bb) { super.postDominates(bb) }
/**
* DEPRECATED: Use `getASuccessor` instead.
*
@@ -151,3 +155,17 @@ class BasicBlock extends BbImpl::BasicBlock {
class ExitBlock extends BasicBlock {
ExitBlock() { this.getLastNode() instanceof ControlFlow::ExitNode }
}
private class BasicBlockAlias = BasicBlock;
module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = BbImpl::ControlFlowNode;
class SuccessorType = BbImpl::SuccessorType;
class BasicBlock = BasicBlockAlias;
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) { BbImpl::dominatingEdge(bb1, bb2) }
predicate entryBlock(BasicBlock bb) { BbImpl::entryBlock(bb) }
}

View File

@@ -157,13 +157,7 @@ private module BaseSsaImpl {
private import BaseSsaImpl
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J
class BasicBlock = J::BasicBlock;
class ControlFlowNode = J::ControlFlowNode;
private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
class SourceVariable = BaseSsaSourceVariable;
/**
@@ -195,7 +189,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
}
}
private module Impl = SsaImplCommon::Make<Location, SsaInput>;
private module Impl = SsaImplCommon::Make<Location, Cfg, SsaInput>;
private import Cached

View File

@@ -69,28 +69,10 @@ private predicate closureFlowStep(Expr e1, Expr e2) {
)
}
private module CaptureInput implements VariableCapture::InputSig<Location> {
private module CaptureInput implements VariableCapture::InputSig<Location, BasicBlock> {
private import java as J
class BasicBlock instanceof J::BasicBlock {
string toString() { result = super.toString() }
ControlFlowNode getNode(int i) { result = super.getNode(i) }
int length() { result = super.length() }
Callable getEnclosingCallable() { result = super.getEnclosingCallable() }
Location getLocation() { result = super.getLocation() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
}
class ControlFlowNode = J::ControlFlowNode;
Callable basicBlockGetEnclosingCallable(BasicBlock bb) { result = bb.getEnclosingCallable() }
//TODO: support capture of `this` in lambdas
class CapturedVariable instanceof LocalScopeVariable {
@@ -165,7 +147,7 @@ class CapturedVariable = CaptureInput::CapturedVariable;
class CapturedParameter = CaptureInput::CapturedParameter;
module CaptureFlow = VariableCapture::Flow<Location, CaptureInput>;
module CaptureFlow = VariableCapture::Flow<Location, Cfg, CaptureInput>;
private CaptureFlow::ClosureNode asClosureNode(Node n) {
result = n.(CaptureNode).getSynthesizedCaptureNode()

View File

@@ -166,13 +166,7 @@ private predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, Basic
uncertainVariableUpdate(v.getQualifier(), n, b, i)
}
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J
class BasicBlock = J::BasicBlock;
class ControlFlowNode = J::ControlFlowNode;
private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
class SourceVariable = SsaSourceVariable;
/**
@@ -214,7 +208,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
}
}
import SsaImplCommon::Make<Location, SsaInput> as Impl
import SsaImplCommon::Make<Location, Cfg, SsaInput> as Impl
final class Definition = Impl::Definition;

View File

@@ -4,7 +4,7 @@ private import semmle.javascript.dataflow.internal.VariableOrThis
private import codeql.dataflow.VariableCapture
private import semmle.javascript.dataflow.internal.sharedlib.DataFlowImplCommon as DataFlowImplCommon
module VariableCaptureConfig implements InputSig<js::Location> {
module VariableCaptureConfig implements InputSig<js::Location, js::Cfg::BasicBlock> {
private js::Function getLambdaFromVariable(js::LocalVariable variable) {
result.getVariable() = variable
or
@@ -106,20 +106,8 @@ module VariableCaptureConfig implements InputSig<js::Location> {
)
}
class ControlFlowNode = js::ControlFlowNode;
final private class JsBasicBlock = js::BasicBlock;
class BasicBlock extends JsBasicBlock {
Callable getEnclosingCallable() { result = this.getContainer().getFunctionBoundary() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) {
df.(js::ReachableJoinBlock).inDominanceFrontierOf(this)
}
Callable basicBlockGetEnclosingCallable(js::Cfg::BasicBlock bb) {
result = bb.getContainer().getFunctionBoundary()
}
class Callable extends js::StmtContainer {
@@ -135,7 +123,7 @@ module VariableCaptureConfig implements InputSig<js::Location> {
class Expr extends js::AST::ValueNode {
/** Holds if the `i`th node of basic block `bb` evaluates this expression. */
predicate hasCfgNode(BasicBlock bb, int i) {
predicate hasCfgNode(js::Cfg::BasicBlock bb, int i) {
// Note: this is overridden for FunctionDeclStmt
bb.getNode(i) = this
}
@@ -180,7 +168,7 @@ module VariableCaptureConfig implements InputSig<js::Location> {
js::Location getLocation() { none() } // Overridden in subclass
predicate hasCfgNode(BasicBlock bb, int i) { none() } // Overridden in subclass
predicate hasCfgNode(js::Cfg::BasicBlock bb, int i) { none() } // Overridden in subclass
// note: langauge-specific
js::DataFlow::Node getSource() { none() } // Overridden in subclass
@@ -217,7 +205,7 @@ module VariableCaptureConfig implements InputSig<js::Location> {
}
/** Holds if the `i`th node of basic block `bb` evaluates this expression. */
override predicate hasCfgNode(BasicBlock bb, int i) {
override predicate hasCfgNode(js::Cfg::BasicBlock bb, int i) {
bb.getNode(i) = this.getCfgNodeOverride()
or
not exists(this.getCfgNodeOverride()) and
@@ -236,7 +224,7 @@ module VariableCaptureConfig implements InputSig<js::Location> {
override CapturedVariable getVariable() { result = variable }
override predicate hasCfgNode(BasicBlock bb, int i) {
override predicate hasCfgNode(js::Cfg::BasicBlock bb, int i) {
// 'i' would normally be bound to 0, but we lower it to -1 so FunctionDeclStmts can be evaluated
// at index 0.
any(js::SsaImplicitInit def).definesAt(bb, _, variable.asLocalVariable()) and i = -1
@@ -244,11 +232,9 @@ module VariableCaptureConfig implements InputSig<js::Location> {
bb.(js::EntryBasicBlock).getContainer() = variable.asThisContainer() and i = -1
}
}
predicate entryBlock(BasicBlock bb) { bb instanceof js::EntryBasicBlock }
}
module VariableCaptureOutput = Flow<js::Location, VariableCaptureConfig>;
module VariableCaptureOutput = Flow<js::Location, js::Cfg, VariableCaptureConfig>;
js::DataFlow::Node getNodeFromClosureNode(VariableCaptureOutput::ClosureNode node) {
result = TValueNode(node.(VariableCaptureOutput::ExprNode).getExpr())
@@ -294,9 +280,9 @@ private module Debug {
relevantContainer(node1.getContainer())
}
predicate readBB(VariableRead read, BasicBlock bb, int i) { read.hasCfgNode(bb, i) }
predicate readBB(VariableRead read, js::Cfg::BasicBlock bb, int i) { read.hasCfgNode(bb, i) }
predicate writeBB(VariableWrite write, BasicBlock bb, int i) { write.hasCfgNode(bb, i) }
predicate writeBB(VariableWrite write, js::Cfg::BasicBlock bb, int i) { write.hasCfgNode(bb, i) }
int captureDegree(js::Function fun) {
result = strictcount(CapturedVariable v | captures(fun, v))

View File

@@ -9,21 +9,7 @@ private import codeql.ssa.Ssa
private import semmle.javascript.internal.BasicBlockInternal as BasicBlockInternal
private import semmle.javascript.dataflow.internal.VariableOrThis
module SsaConfig implements InputSig<js::Location> {
class ControlFlowNode = js::ControlFlowNode;
final private class JsBasicBlock = js::BasicBlock;
class BasicBlock extends JsBasicBlock {
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) {
df.(js::ReachableJoinBlock).inDominanceFrontierOf(this)
}
}
module SsaConfig implements InputSig<js::Location, js::Cfg::BasicBlock> {
class SourceVariable extends LocalVariableOrThis {
SourceVariable() { not this.isCaptured() }
}
@@ -33,7 +19,7 @@ module SsaConfig implements InputSig<js::Location> {
result.getContainer() = container
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(js::Cfg::BasicBlock bb, int i, SourceVariable v, boolean certain) {
certain = true and
(
bb.defAt(i, v.asLocalVariable(), _)
@@ -44,7 +30,7 @@ module SsaConfig implements InputSig<js::Location> {
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(js::Cfg::BasicBlock bb, int i, SourceVariable v, boolean certain) {
bb.useAt(i, v.asLocalVariable(), _) and certain = true
or
certain = true and
@@ -52,7 +38,7 @@ module SsaConfig implements InputSig<js::Location> {
}
}
import Make<js::Location, SsaConfig>
import Make<js::Location, js::Cfg, SsaConfig>
module SsaDataflowInput implements DataFlowIntegrationInputSig {
private import codeql.util.Boolean
@@ -60,7 +46,7 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
class Expr extends js::ControlFlowNode {
Expr() { this = any(SsaConfig::SourceVariable v).getAUse() }
predicate hasCfgNode(SsaConfig::BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(js::Cfg::BasicBlock bb, int i) { this = bb.getNode(i) }
}
predicate ssaDefHasSource(WriteDefinition def) {
@@ -87,9 +73,7 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
* Holds if the evaluation of this guard to `branch` corresponds to the edge
* from `bb1` to `bb2`.
*/
predicate hasValueBranchEdge(
SsaConfig::BasicBlock bb1, SsaConfig::BasicBlock bb2, GuardValue branch
) {
predicate hasValueBranchEdge(js::Cfg::BasicBlock bb1, js::Cfg::BasicBlock bb2, GuardValue branch) {
exists(js::ConditionGuardNode g |
g.getTest() = this and
bb1 = this.getBasicBlock() and
@@ -104,14 +88,14 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig {
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate valueControlsBranchEdge(
SsaConfig::BasicBlock bb1, SsaConfig::BasicBlock bb2, GuardValue branch
js::Cfg::BasicBlock bb1, js::Cfg::BasicBlock bb2, GuardValue branch
) {
this.hasValueBranchEdge(bb1, bb2, branch)
}
}
pragma[inline]
predicate guardDirectlyControlsBlock(Guard guard, SsaConfig::BasicBlock bb, GuardValue branch) {
predicate guardDirectlyControlsBlock(Guard guard, js::Cfg::BasicBlock bb, GuardValue branch) {
exists(js::ConditionGuardNode g |
g.getTest() = guard and
g.dominates(bb) and

View File

@@ -6,6 +6,7 @@
import javascript
private import semmle.javascript.internal.StmtContainers
private import semmle.javascript.internal.CachedStages
private import codeql.controlflow.BasicBlock as BB
/**
* Holds if `nd` starts a new basic block.
@@ -366,4 +367,48 @@ module Public {
)
}
}
final private class FinalBasicBlock = BasicBlock;
module Cfg implements BB::CfgSig<Location> {
private import javascript as Js
private import codeql.util.Unit
class ControlFlowNode = Js::ControlFlowNode;
class SuccessorType = Unit;
class BasicBlock extends FinalBasicBlock {
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor() and exists(t) }
predicate strictlyDominates(BasicBlock bb) {
this.(ReachableBasicBlock).strictlyDominates(bb)
}
predicate dominates(BasicBlock bb) { this.(ReachableBasicBlock).dominates(bb) }
predicate inDominanceFrontier(BasicBlock df) {
df.(ReachableJoinBlock).inDominanceFrontierOf(this)
}
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate strictlyPostDominates(BasicBlock bb) {
this.(ReachableBasicBlock).strictlyPostDominates(bb)
}
predicate postDominates(BasicBlock bb) { this.(ReachableBasicBlock).postDominates(bb) }
}
pragma[nomagic]
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
bb1.getASuccessor() = bb2 and
bb1 = bb2.getImmediateDominator() and
forall(BasicBlock pred | pred = bb2.getAPredecessor() and pred != bb1 | bb2.dominates(pred))
}
predicate entryBlock(BasicBlock bb) { entryBB(bb) }
}
}

View File

@@ -1,6 +1,7 @@
import python
private import semmle.python.pointsto.PointsTo
private import semmle.python.internal.CachedStages
private import codeql.controlflow.BasicBlock as BB
/*
* Note about matching parent and child nodes and CFG splitting:
@@ -1252,3 +1253,54 @@ private predicate end_bb_likely_reachable(BasicBlock b) {
not p = b.getLastNode()
)
}
private class ControlFlowNodeAlias = ControlFlowNode;
final private class FinalBasicBlock = BasicBlock;
module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowNodeAlias;
class SuccessorType = Unit;
class BasicBlock extends FinalBasicBlock {
// Note `PY:BasicBlock` does not have a `getLocation`.
// (Instead it has a complicated location info logic.)
// Using the location of the first node is simple
// and we just need a way to identify the basic block
// during debugging, so this will be serviceable.
Location getLocation() { result = super.getNode(0).getLocation() }
int length() { result = count(int i | exists(this.getNode(i))) }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getASuccessor(SuccessorType t) { result = super.getASuccessor() and exists(t) }
predicate strictlyDominates(BasicBlock bb) { super.strictlyDominates(bb) }
predicate dominates(BasicBlock bb) { super.dominates(bb) }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
/** Unsupported. Do not use. */
predicate strictlyPostDominates(BasicBlock bb) { none() }
/** Unsupported. Do not use. */
predicate postDominates(BasicBlock bb) {
this.strictlyPostDominates(bb) or
this = bb
}
}
pragma[nomagic]
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
bb1.getASuccessor() = bb2 and
bb1 = bb2.getImmediateDominator() and
forall(BasicBlock pred | pred = bb2.getAPredecessor() and pred != bb1 | bb2.dominates(pred))
}
predicate entryBlock(BasicBlock bb) { bb.getNode(0).isEntryNode() }
}

View File

@@ -12,7 +12,7 @@ private import codeql.dataflow.VariableCapture as Shared
// The first is the main implementation, the second is a performance motivated restriction.
// The restriction is to clear any `CapturedVariableContent` before writing a new one
// to avoid long access paths (see the link for a nice explanation).
private module CaptureInput implements Shared::InputSig<Location> {
private module CaptureInput implements Shared::InputSig<Location, Cfg::BasicBlock> {
private import python as PY
additional class ExprCfgNode extends ControlFlowNode {
@@ -23,28 +23,7 @@ private module CaptureInput implements Shared::InputSig<Location> {
predicate isConstructor() { none() }
}
final private class PyBasicBlock = PY::BasicBlock;
class BasicBlock extends PyBasicBlock {
int length() { result = count(int i | exists(this.getNode(i))) }
Callable getEnclosingCallable() { result = this.getScope() }
// Note `PY:BasicBlock` does not have a `getLocation`.
// (Instead it has a complicated location info logic.)
// Using the location of the first node is simple
// and we just need a way to identify the basic block
// during debugging, so this will be serviceable.
Location getLocation() { result = super.getNode(0).getLocation() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
}
class ControlFlowNode = PY::ControlFlowNode;
Callable basicBlockGetEnclosingCallable(Cfg::BasicBlock bb) { result = bb.getScope() }
class CapturedVariable extends LocalVariable {
Function f;
@@ -74,7 +53,7 @@ private module CaptureInput implements Shared::InputSig<Location> {
}
class Expr extends ExprCfgNode {
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(Cfg::BasicBlock bb, int i) { this = bb.getNode(i) }
}
class VariableWrite extends ControlFlowNode {
@@ -84,7 +63,7 @@ private module CaptureInput implements Shared::InputSig<Location> {
CapturedVariable getVariable() { result = v }
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(Cfg::BasicBlock bb, int i) { this = bb.getNode(i) }
}
class VariableRead extends Expr {
@@ -126,7 +105,7 @@ class CapturedVariable = CaptureInput::CapturedVariable;
class ClosureExpr = CaptureInput::ClosureExpr;
module Flow = Shared::Flow<Location, CaptureInput>;
module Flow = Shared::Flow<Location, Cfg, CaptureInput>;
private Flow::ClosureNode asClosureNode(Node n) {
result = n.(SynthCaptureNode).getSynthesizedCaptureNode()

View File

@@ -10,6 +10,7 @@ private import internal.ControlFlowGraphImpl as CfgImpl
private import CfgNodes
private import SuccessorTypes
private import CfgImpl::BasicBlocks as BasicBlocksImpl
private import codeql.controlflow.BasicBlock as BB
/**
* A basic block, that is, a maximal straight-line sequence of control flow nodes
@@ -296,3 +297,21 @@ final class ConditionBlock extends BasicBlock, BasicBlocksImpl::ConditionBasicBl
super.edgeDominates(controlled, s)
}
}
private class BasicBlockAlias = BasicBlock;
private class SuccessorTypeAlias = SuccessorType;
module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = CfgNode;
class SuccessorType = SuccessorTypeAlias;
class BasicBlock = BasicBlockAlias;
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
BasicBlocksImpl::dominatingEdge(bb1, bb2)
}
predicate entryBlock(BasicBlock bb) { bb instanceof EntryBasicBlock }
}

View File

@@ -280,6 +280,7 @@ predicate isNonConstantExpr(CfgNodes::ExprCfgNode n) {
/** Provides logic related to captured variables. */
module VariableCapture {
private import codeql.dataflow.VariableCapture as Shared
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
private predicate closureFlowStep(CfgNodes::ExprCfgNode e1, CfgNodes::ExprCfgNode e2) {
e1 = getALastEvalNode(e2)
@@ -290,23 +291,14 @@ module VariableCapture {
)
}
private module CaptureInput implements Shared::InputSig<Location> {
private module CaptureInput implements Shared::InputSig<Location, BasicBlocks::Cfg::BasicBlock> {
private import codeql.ruby.controlflow.ControlFlowGraph as Cfg
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
private import TaintTrackingPrivate as TaintTrackingPrivate
class BasicBlock extends BasicBlocks::BasicBlock {
Callable getEnclosingCallable() { result = this.getScope() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
Callable basicBlockGetEnclosingCallable(BasicBlocks::Cfg::BasicBlock bb) {
result = bb.getScope()
}
class ControlFlowNode = Cfg::CfgNode;
class CapturedVariable extends LocalVariable {
CapturedVariable() {
this.isCaptured() and
@@ -377,7 +369,7 @@ module VariableCapture {
class ClosureExpr = CaptureInput::ClosureExpr;
module Flow = Shared::Flow<Location, CaptureInput>;
module Flow = Shared::Flow<Location, BasicBlocks::Cfg, CaptureInput>;
private Flow::ClosureNode asClosureNode(Node n) {
result = n.(CaptureNode).getSynthesizedCaptureNode()

View File

@@ -4,18 +4,16 @@ module;
private import codeql.ssa.Ssa as SsaImplCommon
private import codeql.ruby.AST
private import codeql.ruby.CFG as Cfg
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
private import codeql.ruby.controlflow.internal.ControlFlowGraphImpl as ControlFlowGraphImpl
private import codeql.ruby.dataflow.SSA
private import codeql.ruby.ast.Variable
private import Cfg::CfgNodes::ExprNodes
module SsaInput implements SsaImplCommon::InputSig<Location> {
private class BasicBlock = BasicBlocks::Cfg::BasicBlock;
module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
private import codeql.ruby.controlflow.ControlFlowGraph as Cfg
private import codeql.ruby.controlflow.BasicBlocks as BasicBlocks
class BasicBlock = BasicBlocks::BasicBlock;
class ControlFlowNode = Cfg::CfgNode;
class SourceVariable = LocalVariable;
@@ -62,7 +60,7 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
}
}
import SsaImplCommon::Make<Location, SsaInput> as Impl
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
class Definition = Impl::Definition;
@@ -216,15 +214,14 @@ private predicate hasVariableReadWithCapturedWrite(
pragma[noinline]
deprecated private predicate adjacentDefReadExt(
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2,
SsaInput::SourceVariable v
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2, SsaInput::SourceVariable v
) {
Impl::adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
v = def.getSourceVariable()
}
deprecated private predicate adjacentDefReachesReadExt(
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
exists(SsaInput::SourceVariable v | adjacentDefReadExt(def, bb1, i1, bb2, i2, v) |
def.definesAt(v, bb1, i1)
@@ -232,7 +229,7 @@ deprecated private predicate adjacentDefReachesReadExt(
SsaInput::variableRead(bb1, i1, v, true)
)
or
exists(SsaInput::BasicBlock bb3, int i3 |
exists(BasicBlock bb3, int i3 |
adjacentDefReachesReadExt(def, bb1, i1, bb3, i3) and
SsaInput::variableRead(bb3, i3, _, false) and
Impl::adjacentDefReadExt(def, _, bb3, i3, bb2, i2)
@@ -240,7 +237,7 @@ deprecated private predicate adjacentDefReachesReadExt(
}
deprecated private predicate adjacentDefReachesUncertainReadExt(
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
Definition def, BasicBlock bb1, int i1, BasicBlock bb2, int i2
) {
adjacentDefReachesReadExt(def, bb1, i1, bb2, i2) and
SsaInput::variableRead(bb2, i2, _, false)
@@ -248,13 +245,11 @@ deprecated private predicate adjacentDefReachesUncertainReadExt(
/** Same as `lastRefRedef`, but skips uncertain reads. */
pragma[nomagic]
deprecated private predicate lastRefSkipUncertainReadsExt(
Definition def, SsaInput::BasicBlock bb, int i
) {
deprecated private predicate lastRefSkipUncertainReadsExt(Definition def, BasicBlock bb, int i) {
Impl::lastRef(def, bb, i) and
not SsaInput::variableRead(bb, i, def.getSourceVariable(), false)
or
exists(SsaInput::BasicBlock bb0, int i0 |
exists(BasicBlock bb0, int i0 |
Impl::lastRef(def, bb0, i0) and
adjacentDefReachesUncertainReadExt(def, bb, i, bb0, i0)
)
@@ -475,7 +470,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
private import codeql.util.Boolean
class Expr extends Cfg::CfgNodes::ExprCfgNode {
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
}
Expr getARead(Definition def) { result = Cached::getARead(def) }
@@ -491,9 +486,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
* Holds if the evaluation of this guard to `branch` corresponds to the edge
* from `bb1` to `bb2`.
*/
predicate hasValueBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue branch
) {
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue branch) {
exists(Cfg::SuccessorTypes::ConditionalSuccessor s |
this.getBasicBlock() = bb1 and
bb2 = bb1.getASuccessor(s) and
@@ -506,15 +499,13 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
* branch edge from `bb1` to `bb2`. That is, following the edge from
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate valueControlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue branch
) {
predicate valueControlsBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue branch) {
this.hasValueBranchEdge(bb1, bb2, branch)
}
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, GuardValue branch) {
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, GuardValue branch) {
Guards::guardControlsBlock(guard, bb, branch)
}
}

View File

@@ -1,7 +1,10 @@
private import codeql.controlflow.BasicBlock as BB
private import codeql.Locations
private import codeql.rust.controlflow.ControlFlowGraph as ControlFlowGraph
private import internal.ControlFlowGraphImpl as CfgImpl
private import CfgImpl::BasicBlocks as BasicBlocksImpl
final class BasicBlock = BasicBlocksImpl::BasicBlock;
class BasicBlock = BasicBlocksImpl::BasicBlock;
final class EntryBasicBlock = BasicBlocksImpl::EntryBasicBlock;
@@ -14,3 +17,15 @@ final class ConditionBasicBlock = BasicBlocksImpl::ConditionBasicBlock;
final class JoinBasicBlock = BasicBlocksImpl::JoinBasicBlock;
final class JoinPredecessorBasicBlock = BasicBlocksImpl::JoinPredecessorBasicBlock;
module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowGraph::CfgNode;
class SuccessorType = ControlFlowGraph::SuccessorType;
class BasicBlock = BasicBlocksImpl::BasicBlock;
predicate dominatingEdge = BasicBlocksImpl::dominatingEdge/2;
predicate entryBlock(BasicBlock bb) { bb instanceof EntryBasicBlock }
}

View File

@@ -844,6 +844,7 @@ module RustDataFlow implements InputSig<Location> {
module VariableCapture {
private import codeql.rust.internal.CachedStages
private import codeql.dataflow.VariableCapture as SharedVariableCapture
private import codeql.rust.controlflow.BasicBlocks as BasicBlocks
private predicate closureFlowStep(ExprCfgNode e1, ExprCfgNode e2) {
Stages::DataFlowStage::ref() and
@@ -855,22 +856,13 @@ module VariableCapture {
)
}
private module CaptureInput implements SharedVariableCapture::InputSig<Location> {
private module CaptureInput implements
SharedVariableCapture::InputSig<Location, BasicBlocks::BasicBlock>
{
private import rust as Ast
private import codeql.rust.controlflow.BasicBlocks as BasicBlocks
private import codeql.rust.elements.Variable as Variable
class BasicBlock extends BasicBlocks::BasicBlock {
Callable getEnclosingCallable() { result = this.getScope() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
}
class ControlFlowNode = CfgNode;
Callable basicBlockGetEnclosingCallable(BasicBlocks::BasicBlock bb) { result = bb.getScope() }
class CapturedVariable extends Variable {
CapturedVariable() { this.isCaptured() }
@@ -887,7 +879,7 @@ module VariableCapture {
}
class Expr extends CfgNode {
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(BasicBlocks::BasicBlock bb, int i) { this = bb.getNode(i) }
}
class VariableWrite extends Expr {
@@ -949,7 +941,7 @@ module VariableCapture {
class CapturedVariable = CaptureInput::CapturedVariable;
module Flow = SharedVariableCapture::Flow<Location, CaptureInput>;
module Flow = SharedVariableCapture::Flow<Location, BasicBlocks::Cfg, CaptureInput>;
private Flow::ClosureNode asClosureNode(Node n) {
result = n.(CaptureNode).getSynthesizedCaptureNode()

View File

@@ -54,11 +54,7 @@ private predicate variableReadCertain(BasicBlock bb, int i, VariableAccess va, V
)
}
module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = BasicBlocks::BasicBlock;
class ControlFlowNode = CfgNode;
module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
class SourceVariable = Variable;
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
@@ -87,7 +83,7 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
}
}
import SsaImplCommon::Make<Location, SsaInput> as Impl
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
class Definition = Impl::Definition;
@@ -320,7 +316,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
private import codeql.util.Boolean
class Expr extends CfgNodes::AstCfgNode {
predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) }
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) }
}
Expr getARead(Definition def) { result = Cached::getARead(def) }
@@ -353,9 +349,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
* Holds if the evaluation of this guard to `branch` corresponds to the edge
* from `bb1` to `bb2`.
*/
predicate hasValueBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue branch
) {
predicate hasValueBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue branch) {
exists(Cfg::ConditionalSuccessor s |
this = bb1.getANode() and
bb2 = bb1.getASuccessor(s) and
@@ -368,15 +362,13 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
* branch edge from `bb1` to `bb2`. That is, following the edge from
* `bb1` to `bb2` implies that this guard evaluated to `branch`.
*/
predicate valueControlsBranchEdge(
SsaInput::BasicBlock bb1, SsaInput::BasicBlock bb2, GuardValue branch
) {
predicate valueControlsBranchEdge(BasicBlock bb1, BasicBlock bb2, GuardValue branch) {
this.hasValueBranchEdge(bb1, bb2, branch)
}
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, GuardValue branch) {
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, GuardValue branch) {
exists(ConditionBasicBlock conditionBlock, ConditionalSuccessor s |
guard = conditionBlock.getLastNode() and
s.getValue() = branch and

View File

@@ -1609,7 +1609,7 @@ module MakeWithSplitting<
private module BasicBlockImpl = BB::Make<Location, BasicBlockInputSig>;
final class BasicBlock = BasicBlockImpl::BasicBlock;
class BasicBlock = BasicBlockImpl::BasicBlock;
predicate dominatingEdge = BasicBlockImpl::dominatingEdge/2;

View File

@@ -1,9 +1,11 @@
/** Provides classes representing basic blocks. */
private import swift
private import ControlFlowGraph
private import internal.ControlFlowGraphImpl as CfgImpl
private import SuccessorTypes
private import CfgImpl::BasicBlocks as BasicBlocksImpl
private import codeql.controlflow.BasicBlock as BB
/**
* A basic block, that is, a maximal straight-line sequence of control flow nodes
@@ -111,3 +113,23 @@ final class ConditionBlock extends BasicBlock, BasicBlocksImpl::ConditionBasicBl
super.edgeDominates(controlled, s)
}
}
private class BasicBlockAlias = BasicBlock;
private class ControlFlowNodeAlias = ControlFlowNode;
private class SuccessorTypeAlias = SuccessorType;
module Cfg implements BB::CfgSig<Location> {
class ControlFlowNode = ControlFlowNodeAlias;
class SuccessorType = SuccessorTypeAlias;
class BasicBlock = BasicBlockAlias;
predicate dominatingEdge(BasicBlock bb1, BasicBlock bb2) {
BasicBlocksImpl::dominatingEdge(bb1, bb2)
}
predicate entryBlock(BasicBlock bb) { bb instanceof EntryBasicBlock }
}

View File

@@ -6,15 +6,10 @@ module Ssa {
private import codeql.swift.controlflow.ControlFlowGraph
private import codeql.swift.controlflow.BasicBlocks as BasicBlocks
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlocks::BasicBlock> {
private import internal.DataFlowPrivate
private import codeql.swift.controlflow.ControlFlowGraph as Cfg
private import codeql.swift.controlflow.CfgNodes
class BasicBlock = BasicBlocks::BasicBlock;
class ControlFlowNode = Cfg::ControlFlowNode;
private newtype TSourceVariable =
TNormalSourceVariable(VarDecl v) or
TKeyPathSourceVariable(EntryNode entry) { entry.getScope() instanceof KeyPathExpr }
@@ -55,7 +50,7 @@ module Ssa {
override EntryNode asKeyPath() { result = enter }
}
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableWrite(BasicBlocks::BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(AssignExpr assign |
bb.getNode(i).getNode().asAstNode() = assign and
assign.getDest() = v.getAnAccess() and
@@ -93,7 +88,7 @@ module Ssa {
)
}
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
predicate variableRead(BasicBlocks::BasicBlock bb, int i, SourceVariable v, boolean certain) {
exists(DeclRefExpr ref |
not isLValue(ref) and
bb.getNode(i).getNode().asAstNode() = ref and
@@ -127,7 +122,7 @@ module Ssa {
/**
* INTERNAL: Do not use.
*/
module SsaImpl = SsaImplCommon::Make<Location, SsaInput>;
module SsaImpl = SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput>;
cached
class Definition extends SsaImpl::Definition {
@@ -136,7 +131,7 @@ module Ssa {
cached
ControlFlowNode getARead() {
exists(SsaInput::SourceVariable v, SsaInput::BasicBlock bb, int i |
exists(SsaInput::SourceVariable v, BasicBlocks::BasicBlock bb, int i |
SsaImpl::ssaDefReachesRead(v, this, bb, i) and
SsaInput::variableRead(bb, i, v, true) and
result = bb.getNode(i)
@@ -145,7 +140,7 @@ module Ssa {
cached
ControlFlowNode getAFirstRead() {
exists(SsaInput::BasicBlock bb, int i |
exists(BasicBlocks::BasicBlock bb, int i |
SsaImpl::firstUse(this, bb, i, true) and
result = bb.getNode(i)
)
@@ -154,7 +149,7 @@ module Ssa {
cached
predicate adjacentReadPair(ControlFlowNode read1, ControlFlowNode read2) {
read1 = this.getARead() and
exists(SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 |
exists(BasicBlocks::BasicBlock bb1, int i1, BasicBlocks::BasicBlock bb2, int i2 |
read1 = bb1.getNode(i1) and
SsaImpl::adjacentUseUse(bb1, i1, bb2, i2, _, true) and
read2 = bb2.getNode(i2)
@@ -162,7 +157,7 @@ module Ssa {
}
cached
deprecated predicate lastRefRedef(SsaInput::BasicBlock bb, int i, Definition next) {
deprecated predicate lastRefRedef(BasicBlocks::BasicBlock bb, int i, Definition next) {
SsaImpl::lastRefRedef(this, bb, i, next)
}
}
@@ -171,7 +166,7 @@ module Ssa {
class WriteDefinition extends Definition, SsaImpl::WriteDefinition {
cached
override Location getLocation() {
exists(SsaInput::BasicBlock bb, int i |
exists(BasicBlocks::BasicBlock bb, int i |
this.definesAt(_, bb, i) and
result = bb.getNode(i).getLocation()
)
@@ -183,19 +178,19 @@ module Ssa {
*/
cached
predicate assigns(CfgNode value) {
exists(AssignExpr a, SsaInput::BasicBlock bb, int i |
exists(AssignExpr a, BasicBlocks::BasicBlock bb, int i |
this.definesAt(_, bb, i) and
a = bb.getNode(i).getNode().asAstNode() and
value.getNode().asAstNode() = a.getSource()
)
or
exists(SsaInput::BasicBlock bb, int blockIndex, NamedPattern np |
exists(BasicBlocks::BasicBlock bb, int blockIndex, NamedPattern np |
this.definesAt(_, bb, blockIndex) and
np = bb.getNode(blockIndex).getNode().asAstNode() and
value.getNode().asAstNode() = np
)
or
exists(SsaInput::BasicBlock bb, int blockIndex, ConditionElement ce, Expr init |
exists(BasicBlocks::BasicBlock bb, int blockIndex, ConditionElement ce, Expr init |
this.definesAt(_, bb, blockIndex) and
ce.getPattern() = bb.getNode(blockIndex).getNode().asAstNode() and
init = ce.getInitializer() and
@@ -210,14 +205,14 @@ module Ssa {
class PhiDefinition extends Definition, SsaImpl::PhiNode {
cached
override Location getLocation() {
exists(SsaInput::BasicBlock bb |
exists(BasicBlocks::BasicBlock bb |
this.definesAt(_, bb, _) and
result = bb.getLocation()
)
}
cached
Definition getPhiInput(SsaInput::BasicBlock bb) {
Definition getPhiInput(BasicBlocks::BasicBlock bb) {
SsaImpl::phiHasInputFromBlock(this, result, bb)
}

View File

@@ -882,30 +882,11 @@ private predicate closureFlowStep(CaptureInput::Expr e1, CaptureInput::Expr e2)
e2.(Pattern).getImmediateMatchingExpr() = e1
}
private module CaptureInput implements VariableCapture::InputSig<Location> {
private module CaptureInput implements VariableCapture::InputSig<Location, BasicBlock> {
private import swift as S
private import codeql.swift.controlflow.ControlFlowGraph as Cfg
private import codeql.swift.controlflow.BasicBlocks as B
class BasicBlock instanceof B::BasicBlock {
string toString() { result = super.toString() }
ControlFlowNode getNode(int i) { result = super.getNode(i) }
int length() { result = super.length() }
Callable getEnclosingCallable() { result = super.getScope() }
Location getLocation() { result = super.getLocation() }
BasicBlock getASuccessor() { result = super.getASuccessor() }
BasicBlock getImmediateDominator() { result = super.getImmediateDominator() }
predicate inDominanceFrontier(BasicBlock df) { super.inDominanceFrontier(df) }
}
class ControlFlowNode = Cfg::ControlFlowNode;
Callable basicBlockGetEnclosingCallable(BasicBlock bb) { result = bb.getScope() }
class CapturedVariable instanceof S::VarDecl {
CapturedVariable() {
@@ -927,9 +908,7 @@ private module CaptureInput implements VariableCapture::InputSig<Location> {
Location getLocation() { result = super.getLocation() }
predicate hasCfgNode(BasicBlock bb, int i) {
this = bb.(B::BasicBlock).getNode(i).getNode().asAstNode()
}
predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i).getNode().asAstNode() }
}
class VariableWrite extends Expr {
@@ -1001,7 +980,7 @@ class CapturedVariable = CaptureInput::CapturedVariable;
class CapturedParameter = CaptureInput::CapturedParameter;
module CaptureFlow = VariableCapture::Flow<Location, CaptureInput>;
module CaptureFlow = VariableCapture::Flow<Location, Cfg, CaptureInput>;
private CaptureFlow::ClosureNode asClosureNode(Node n) {
result = n.(CaptureNode).getSynthesizedCaptureNode()