mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Languages: Adapt to api changes.
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user