mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
VariableCapture: Replace phi-read reference with SSA data flow integration module.
This commit is contained in:
@@ -699,6 +699,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
class SourceVariable = CaptureContainer;
|
||||
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable cc, boolean certain) {
|
||||
Cached::ref() and
|
||||
(
|
||||
exists(CapturedVariable v | cc = TVariable(v) and captureWrite(v, bb, i, true, _))
|
||||
or
|
||||
@@ -721,23 +722,55 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
|
||||
private module CaptureSsa = Ssa::Make<Location, CaptureSsaInput>;
|
||||
|
||||
private newtype TClosureNode =
|
||||
TSynthRead(CapturedVariable v, BasicBlock bb, int i, Boolean isPost) {
|
||||
synthRead(v, bb, i, _, _)
|
||||
} or
|
||||
TSynthThisQualifier(BasicBlock bb, int i, Boolean isPost) { synthThisQualifier(bb, i) } or
|
||||
TSynthPhi(CaptureSsa::DefinitionExt phi) {
|
||||
phi instanceof CaptureSsa::PhiNode or phi instanceof CaptureSsa::PhiReadNode
|
||||
} or
|
||||
TExprNode(Expr expr, Boolean isPost) {
|
||||
expr instanceof VariableRead
|
||||
or
|
||||
synthRead(_, _, _, _, expr)
|
||||
} or
|
||||
TParamNode(CapturedParameter p) or
|
||||
TThisParamNode(Callable c) { captureAccess(_, c) } or
|
||||
TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
|
||||
TVariableWriteSourceNode(VariableWrite write)
|
||||
private module DataFlowIntegrationInput implements CaptureSsa::DataFlowIntegrationInputSig {
|
||||
private import codeql.util.Void
|
||||
|
||||
class Expr instanceof Input::ControlFlowNode {
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasCfgNode(BasicBlock bb, int i) { bb.getNode(i) = this }
|
||||
}
|
||||
|
||||
class Guard extends Void {
|
||||
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) { none() }
|
||||
}
|
||||
|
||||
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) { none() }
|
||||
|
||||
predicate includeWriteDefsInFlowStep() { none() }
|
||||
|
||||
predicate supportBarrierGuardsOnPhiEdges() { none() }
|
||||
}
|
||||
|
||||
private module SsaFlow = CaptureSsa::DataFlowIntegration<DataFlowIntegrationInput>;
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
predicate ref() { any() }
|
||||
|
||||
cached
|
||||
predicate backref() { localFlowStep(_, _) implies any() }
|
||||
|
||||
cached
|
||||
newtype TClosureNode =
|
||||
TSynthRead(CapturedVariable v, BasicBlock bb, int i, Boolean isPost) {
|
||||
synthRead(v, bb, i, _, _)
|
||||
} or
|
||||
TSynthThisQualifier(BasicBlock bb, int i, Boolean isPost) { synthThisQualifier(bb, i) } or
|
||||
TSynthSsa(SsaFlow::SsaNode n) or
|
||||
TExprNode(Expr expr, Boolean isPost) {
|
||||
expr instanceof VariableRead
|
||||
or
|
||||
synthRead(_, _, _, _, expr)
|
||||
} or
|
||||
TParamNode(CapturedParameter p) or
|
||||
TThisParamNode(Callable c) { captureAccess(_, c) } or
|
||||
TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
|
||||
TVariableWriteSourceNode(VariableWrite write)
|
||||
}
|
||||
|
||||
private import Cached
|
||||
|
||||
class ClosureNode extends TClosureNode {
|
||||
/** Gets a textual representation of this node. */
|
||||
@@ -746,11 +779,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
or
|
||||
result = "this" and this = TSynthThisQualifier(_, _, _)
|
||||
or
|
||||
exists(CaptureSsa::DefinitionExt phi, CaptureContainer cc |
|
||||
this = TSynthPhi(phi) and
|
||||
phi.definesAt(cc, _, _, _) and
|
||||
result = "phi(" + cc.toString() + ")"
|
||||
)
|
||||
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and result = n.toString())
|
||||
or
|
||||
exists(Expr expr, boolean isPost | this = TExprNode(expr, isPost) |
|
||||
isPost = false and result = expr.toString()
|
||||
@@ -784,9 +813,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
captureWrite(_, bb, i, false, any(VariableWrite vw | result = vw.getLocation()))
|
||||
)
|
||||
or
|
||||
exists(CaptureSsa::DefinitionExt phi, BasicBlock bb |
|
||||
this = TSynthPhi(phi) and phi.definesAt(_, bb, _, _) and result = bb.getLocation()
|
||||
)
|
||||
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and result = n.getLocation())
|
||||
or
|
||||
exists(Expr expr | this = TExprNode(expr, _) and result = expr.getLocation())
|
||||
or
|
||||
@@ -802,7 +829,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
}
|
||||
}
|
||||
|
||||
private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthPhi;
|
||||
private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthSsa;
|
||||
|
||||
class SynthesizedCaptureNode extends ClosureNode, TSynthesizedCaptureNode {
|
||||
BasicBlock getBasicBlock() {
|
||||
@@ -810,9 +837,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
or
|
||||
this = TSynthThisQualifier(result, _, _)
|
||||
or
|
||||
exists(CaptureSsa::DefinitionExt phi |
|
||||
this = TSynthPhi(phi) and phi.definesAt(_, result, _, _)
|
||||
)
|
||||
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getBasicBlock() = result)
|
||||
}
|
||||
|
||||
Callable getEnclosingCallable() { result = this.getBasicBlock().getEnclosingCallable() }
|
||||
@@ -820,17 +845,13 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
predicate isVariableAccess(CapturedVariable v) {
|
||||
this = TSynthRead(v, _, _, _)
|
||||
or
|
||||
exists(CaptureSsa::DefinitionExt phi |
|
||||
this = TSynthPhi(phi) and phi.definesAt(TVariable(v), _, _, _)
|
||||
)
|
||||
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TVariable(v))
|
||||
}
|
||||
|
||||
predicate isInstanceAccess() {
|
||||
this instanceof TSynthThisQualifier
|
||||
or
|
||||
exists(CaptureSsa::DefinitionExt phi |
|
||||
this = TSynthPhi(phi) and phi.definesAt(TThis(_), _, _, _)
|
||||
)
|
||||
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TThis(_))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -872,18 +893,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
)
|
||||
}
|
||||
|
||||
private predicate step(CaptureContainer cc, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
|
||||
CaptureSsa::adjacentDefReadExt(_, cc, bb1, i1, bb2, i2)
|
||||
}
|
||||
|
||||
private predicate stepToPhi(CaptureContainer cc, BasicBlock bb, int i, TSynthPhi phi) {
|
||||
exists(CaptureSsa::DefinitionExt next |
|
||||
CaptureSsa::lastRefRedefExt(_, cc, bb, i, next) and
|
||||
phi = TSynthPhi(next)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate ssaAccessAt(
|
||||
private predicate ssaReadAt(
|
||||
ClosureNode n, CaptureContainer cc, boolean isPost, BasicBlock bb, int i
|
||||
) {
|
||||
exists(CapturedVariable v |
|
||||
@@ -894,49 +904,57 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
|
||||
or
|
||||
n = TSynthThisQualifier(bb, i, isPost) and cc = TThis(bb.getEnclosingCallable())
|
||||
or
|
||||
exists(CaptureSsa::DefinitionExt phi |
|
||||
n = TSynthPhi(phi) and phi.definesAt(cc, bb, i, _) and isPost = false
|
||||
)
|
||||
or
|
||||
exists(VariableRead vr, CapturedVariable v |
|
||||
captureRead(v, bb, i, true, vr) and
|
||||
n = TExprNode(vr, isPost) and
|
||||
cc = TVariable(v)
|
||||
)
|
||||
or
|
||||
}
|
||||
|
||||
private predicate ssaWriteAt(ClosureNode n, CaptureContainer cc, BasicBlock bb, int i) {
|
||||
exists(VariableWrite vw, CapturedVariable v |
|
||||
captureWrite(v, bb, i, true, vw) and
|
||||
n = TVariableWriteSourceNode(vw) and
|
||||
isPost = false and
|
||||
cc = TVariable(v)
|
||||
)
|
||||
or
|
||||
exists(CapturedParameter p |
|
||||
entryDef(cc, bb, i) and
|
||||
cc = TVariable(p) and
|
||||
n = TParamNode(p) and
|
||||
isPost = false
|
||||
n = TParamNode(p)
|
||||
)
|
||||
or
|
||||
exists(Callable c |
|
||||
entryDef(cc, bb, i) and
|
||||
cc = TThis(c) and
|
||||
n = TThisParamNode(c) and
|
||||
isPost = false
|
||||
n = TThisParamNode(c)
|
||||
)
|
||||
}
|
||||
|
||||
predicate localFlowStep(ClosureNode node1, ClosureNode node2) {
|
||||
exists(CaptureContainer cc, BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
step(cc, bb1, i1, bb2, i2) and
|
||||
ssaAccessAt(node1, pragma[only_bind_into](cc), _, bb1, i1) and
|
||||
ssaAccessAt(node2, pragma[only_bind_into](cc), false, bb2, i2)
|
||||
bindingset[result, cc]
|
||||
pragma[inline_late]
|
||||
private SsaFlow::Node asNode(CaptureContainer cc, ClosureNode n) {
|
||||
n = TSynthSsa(result)
|
||||
or
|
||||
exists(BasicBlock bb, int i |
|
||||
result.(SsaFlow::ExprNode).getExpr().hasCfgNode(bb, i) and
|
||||
ssaReadAt(n, cc, false, bb, i)
|
||||
)
|
||||
or
|
||||
exists(CaptureContainer cc, BasicBlock bb, int i |
|
||||
stepToPhi(cc, bb, i, node2) and
|
||||
ssaAccessAt(node1, cc, _, bb, i)
|
||||
exists(BasicBlock bb, int i |
|
||||
result.(SsaFlow::ExprPostUpdateNode).getExpr().hasCfgNode(bb, i) and
|
||||
ssaReadAt(n, cc, true, bb, i)
|
||||
)
|
||||
or
|
||||
exists(BasicBlock bb, int i |
|
||||
result.(SsaFlow::WriteDefSourceNode).getDefinition().definesAt(cc, bb, i) and
|
||||
ssaWriteAt(n, cc, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate localFlowStep(ClosureNode n1, ClosureNode n2) {
|
||||
exists(CaptureContainer cc | SsaFlow::localFlowStep(cc, asNode(cc, n1), asNode(cc, n2), _))
|
||||
}
|
||||
|
||||
private predicate storeStepClosure(
|
||||
|
||||
Reference in New Issue
Block a user