Skip to content

Commit ca6444c

Browse files
committed
VariableCapture: Replace phi-read reference with SSA data flow integration module.
1 parent e8e9403 commit ca6444c

File tree

1 file changed

+83
-65
lines changed

1 file changed

+83
-65
lines changed

shared/dataflow/codeql/dataflow/VariableCapture.qll

+83-65
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
699699
class SourceVariable = CaptureContainer;
700700

701701
predicate variableWrite(BasicBlock bb, int i, SourceVariable cc, boolean certain) {
702+
Cached::ref() and
702703
(
703704
exists(CapturedVariable v | cc = TVariable(v) and captureWrite(v, bb, i, true, _))
704705
or
@@ -721,23 +722,55 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
721722

722723
private module CaptureSsa = Ssa::Make<Location, CaptureSsaInput>;
723724

724-
private newtype TClosureNode =
725-
TSynthRead(CapturedVariable v, BasicBlock bb, int i, Boolean isPost) {
726-
synthRead(v, bb, i, _, _)
727-
} or
728-
TSynthThisQualifier(BasicBlock bb, int i, Boolean isPost) { synthThisQualifier(bb, i) } or
729-
TSynthPhi(CaptureSsa::DefinitionExt phi) {
730-
phi instanceof CaptureSsa::PhiNode or phi instanceof CaptureSsa::PhiReadNode
731-
} or
732-
TExprNode(Expr expr, Boolean isPost) {
733-
expr instanceof VariableRead
734-
or
735-
synthRead(_, _, _, _, expr)
736-
} or
737-
TParamNode(CapturedParameter p) or
738-
TThisParamNode(Callable c) { captureAccess(_, c) } or
739-
TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
740-
TVariableWriteSourceNode(VariableWrite write)
725+
private module DataFlowIntegrationInput implements CaptureSsa::DataFlowIntegrationInputSig {
726+
private import codeql.util.Void
727+
728+
class Expr instanceof Input::ControlFlowNode {
729+
string toString() { result = super.toString() }
730+
731+
predicate hasCfgNode(BasicBlock bb, int i) { bb.getNode(i) = this }
732+
}
733+
734+
class Guard extends Void {
735+
predicate controlsBranchEdge(BasicBlock bb1, BasicBlock bb2, boolean branch) { none() }
736+
}
737+
738+
predicate guardDirectlyControlsBlock(Guard guard, BasicBlock bb, boolean branch) { none() }
739+
740+
predicate includeWriteDefsInFlowStep() { none() }
741+
742+
predicate supportBarrierGuardsOnPhiEdges() { none() }
743+
}
744+
745+
private module SsaFlow = CaptureSsa::DataFlowIntegration<DataFlowIntegrationInput>;
746+
747+
cached
748+
private module Cached {
749+
cached
750+
predicate ref() { any() }
751+
752+
cached
753+
predicate backref() { localFlowStep(_, _) implies any() }
754+
755+
cached
756+
newtype TClosureNode =
757+
TSynthRead(CapturedVariable v, BasicBlock bb, int i, Boolean isPost) {
758+
synthRead(v, bb, i, _, _)
759+
} or
760+
TSynthThisQualifier(BasicBlock bb, int i, Boolean isPost) { synthThisQualifier(bb, i) } or
761+
TSynthSsa(SsaFlow::SsaNode n) or
762+
TExprNode(Expr expr, Boolean isPost) {
763+
expr instanceof VariableRead
764+
or
765+
synthRead(_, _, _, _, expr)
766+
} or
767+
TParamNode(CapturedParameter p) or
768+
TThisParamNode(Callable c) { captureAccess(_, c) } or
769+
TMallocNode(ClosureExpr ce) { hasConstructorCapture(ce, _) } or
770+
TVariableWriteSourceNode(VariableWrite write)
771+
}
772+
773+
private import Cached
741774

742775
class ClosureNode extends TClosureNode {
743776
/** Gets a textual representation of this node. */
@@ -746,11 +779,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
746779
or
747780
result = "this" and this = TSynthThisQualifier(_, _, _)
748781
or
749-
exists(CaptureSsa::DefinitionExt phi, CaptureContainer cc |
750-
this = TSynthPhi(phi) and
751-
phi.definesAt(cc, _, _, _) and
752-
result = "phi(" + cc.toString() + ")"
753-
)
782+
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and result = n.toString())
754783
or
755784
exists(Expr expr, boolean isPost | this = TExprNode(expr, isPost) |
756785
isPost = false and result = expr.toString()
@@ -784,9 +813,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
784813
captureWrite(_, bb, i, false, any(VariableWrite vw | result = vw.getLocation()))
785814
)
786815
or
787-
exists(CaptureSsa::DefinitionExt phi, BasicBlock bb |
788-
this = TSynthPhi(phi) and phi.definesAt(_, bb, _, _) and result = bb.getLocation()
789-
)
816+
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and result = n.getLocation())
790817
or
791818
exists(Expr expr | this = TExprNode(expr, _) and result = expr.getLocation())
792819
or
@@ -802,35 +829,29 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
802829
}
803830
}
804831

805-
private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthPhi;
832+
private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthSsa;
806833

807834
class SynthesizedCaptureNode extends ClosureNode, TSynthesizedCaptureNode {
808835
BasicBlock getBasicBlock() {
809836
this = TSynthRead(_, result, _, _)
810837
or
811838
this = TSynthThisQualifier(result, _, _)
812839
or
813-
exists(CaptureSsa::DefinitionExt phi |
814-
this = TSynthPhi(phi) and phi.definesAt(_, result, _, _)
815-
)
840+
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getBasicBlock() = result)
816841
}
817842

818843
Callable getEnclosingCallable() { result = this.getBasicBlock().getEnclosingCallable() }
819844

820845
predicate isVariableAccess(CapturedVariable v) {
821846
this = TSynthRead(v, _, _, _)
822847
or
823-
exists(CaptureSsa::DefinitionExt phi |
824-
this = TSynthPhi(phi) and phi.definesAt(TVariable(v), _, _, _)
825-
)
848+
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TVariable(v))
826849
}
827850

828851
predicate isInstanceAccess() {
829852
this instanceof TSynthThisQualifier
830853
or
831-
exists(CaptureSsa::DefinitionExt phi |
832-
this = TSynthPhi(phi) and phi.definesAt(TThis(_), _, _, _)
833-
)
854+
exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TThis(_))
834855
}
835856
}
836857

@@ -872,18 +893,7 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
872893
)
873894
}
874895

875-
private predicate step(CaptureContainer cc, BasicBlock bb1, int i1, BasicBlock bb2, int i2) {
876-
CaptureSsa::adjacentDefReadExt(_, cc, bb1, i1, bb2, i2)
877-
}
878-
879-
private predicate stepToPhi(CaptureContainer cc, BasicBlock bb, int i, TSynthPhi phi) {
880-
exists(CaptureSsa::DefinitionExt next |
881-
CaptureSsa::lastRefRedefExt(_, cc, bb, i, next) and
882-
phi = TSynthPhi(next)
883-
)
884-
}
885-
886-
private predicate ssaAccessAt(
896+
private predicate ssaReadAt(
887897
ClosureNode n, CaptureContainer cc, boolean isPost, BasicBlock bb, int i
888898
) {
889899
exists(CapturedVariable v |
@@ -894,49 +904,57 @@ module Flow<LocationSig Location, InputSig<Location> Input> implements OutputSig
894904
or
895905
n = TSynthThisQualifier(bb, i, isPost) and cc = TThis(bb.getEnclosingCallable())
896906
or
897-
exists(CaptureSsa::DefinitionExt phi |
898-
n = TSynthPhi(phi) and phi.definesAt(cc, bb, i, _) and isPost = false
899-
)
900-
or
901907
exists(VariableRead vr, CapturedVariable v |
902908
captureRead(v, bb, i, true, vr) and
903909
n = TExprNode(vr, isPost) and
904910
cc = TVariable(v)
905911
)
906-
or
912+
}
913+
914+
private predicate ssaWriteAt(ClosureNode n, CaptureContainer cc, BasicBlock bb, int i) {
907915
exists(VariableWrite vw, CapturedVariable v |
908916
captureWrite(v, bb, i, true, vw) and
909917
n = TVariableWriteSourceNode(vw) and
910-
isPost = false and
911918
cc = TVariable(v)
912919
)
913920
or
914921
exists(CapturedParameter p |
915922
entryDef(cc, bb, i) and
916923
cc = TVariable(p) and
917-
n = TParamNode(p) and
918-
isPost = false
924+
n = TParamNode(p)
919925
)
920926
or
921927
exists(Callable c |
922928
entryDef(cc, bb, i) and
923929
cc = TThis(c) and
924-
n = TThisParamNode(c) and
925-
isPost = false
930+
n = TThisParamNode(c)
926931
)
927932
}
928933

929-
predicate localFlowStep(ClosureNode node1, ClosureNode node2) {
930-
exists(CaptureContainer cc, BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
931-
step(cc, bb1, i1, bb2, i2) and
932-
ssaAccessAt(node1, pragma[only_bind_into](cc), _, bb1, i1) and
933-
ssaAccessAt(node2, pragma[only_bind_into](cc), false, bb2, i2)
934+
bindingset[result, cc]
935+
pragma[inline_late]
936+
private SsaFlow::Node asNode(CaptureContainer cc, ClosureNode n) {
937+
n = TSynthSsa(result)
938+
or
939+
exists(BasicBlock bb, int i |
940+
result.(SsaFlow::ExprNode).getExpr().hasCfgNode(bb, i) and
941+
ssaReadAt(n, cc, false, bb, i)
934942
)
935943
or
936-
exists(CaptureContainer cc, BasicBlock bb, int i |
937-
stepToPhi(cc, bb, i, node2) and
938-
ssaAccessAt(node1, cc, _, bb, i)
944+
exists(BasicBlock bb, int i |
945+
result.(SsaFlow::ExprPostUpdateNode).getExpr().hasCfgNode(bb, i) and
946+
ssaReadAt(n, cc, true, bb, i)
939947
)
948+
or
949+
exists(BasicBlock bb, int i |
950+
result.(SsaFlow::WriteDefSourceNode).getDefinition().definesAt(cc, bb, i) and
951+
ssaWriteAt(n, cc, bb, i)
952+
)
953+
}
954+
955+
cached
956+
predicate localFlowStep(ClosureNode n1, ClosureNode n2) {
957+
exists(CaptureContainer cc | SsaFlow::localFlowStep(cc, asNode(cc, n1), asNode(cc, n2), _))
940958
}
941959

942960
private predicate storeStepClosure(

0 commit comments

Comments
 (0)