@@ -87,39 +87,37 @@ class SsaInputDefinitionExt extends SsaImpl::DefinitionExt {
8787
8888/** Provides predicates related to local data flow. */
8989module LocalFlow {
90- /**
91- * Holds if `nodeFrom` is a node for SSA definition `def`, which can reach `next`.
92- */
93- pragma [ nomagic]
94- private predicate localFlowSsaInputFromDef (
95- SsaDefinitionExtNode nodeFrom , SsaImpl:: DefinitionExt def , SsaInputNode nodeTo
96- ) {
97- exists ( BasicBlock bb , int i , BasicBlock input , SsaInputDefinitionExt next |
98- next .hasInputFromBlock ( def , bb , i , input ) and
99- def = nodeFrom .getDefinitionExt ( ) and
100- def .definesAt ( _, bb , i , _) and
101- nodeTo = TSsaInputNode ( next , input )
102- )
103- }
104-
105- /**
106- * Holds if `nodeFrom` is a last read of SSA definition `def`, which
107- * can reach `nodeTo`.
108- */
109- pragma [ nomagic]
110- predicate localFlowSsaInputFromRead ( SsaImpl:: DefinitionExt def , Node nodeFrom , SsaInputNode nodeTo ) {
111- exists (
112- BasicBlock bb , int i , CfgNodes:: ExprCfgNode exprFrom , BasicBlock input ,
113- SsaInputDefinitionExt next
114- |
115- next .hasInputFromBlock ( def , bb , i , input ) and
116- exprFrom = bb .getNode ( i ) and
117- exprFrom .getExpr ( ) instanceof VariableReadAccess and
118- exprFrom = [ nodeFrom .asExpr ( ) , nodeFrom .( PostUpdateNodeImpl ) .getPreUpdateNode ( ) .asExpr ( ) ] and
119- nodeTo = TSsaInputNode ( next , input )
120- )
121- }
122-
90+ // /**
91+ // * Holds if `nodeFrom` is a node for SSA definition `def`, which can reach `next`.
92+ // */
93+ // pragma[nomagic]
94+ // private predicate localFlowSsaInputFromDef(
95+ // SsaDefinitionExtNode nodeFrom, SsaImpl::DefinitionExt def, SsaInputNode nodeTo
96+ // ) {
97+ // exists(BasicBlock bb, int i, BasicBlock input, SsaInputDefinitionExt next |
98+ // next.hasInputFromBlock(def, bb, i, input) and
99+ // def = nodeFrom.getDefinitionExt() and
100+ // def.definesAt(_, bb, i, _) and
101+ // nodeTo = TSsaInputNode(next, input)
102+ // )
103+ // }
104+ // /**
105+ // * Holds if `nodeFrom` is a last read of SSA definition `def`, which
106+ // * can reach `nodeTo`.
107+ // */
108+ // pragma[nomagic]
109+ // predicate localFlowSsaInputFromRead(SsaImpl::DefinitionExt def, Node nodeFrom, SsaInputNode nodeTo) {
110+ // exists(
111+ // BasicBlock bb, int i, CfgNodes::ExprCfgNode exprFrom, BasicBlock input,
112+ // SsaInputDefinitionExt next
113+ // |
114+ // next.hasInputFromBlock(def, bb, i, input) and
115+ // exprFrom = bb.getNode(i) and
116+ // exprFrom.getExpr() instanceof VariableReadAccess and
117+ // exprFrom = [nodeFrom.asExpr(), nodeFrom.(PostUpdateNodeImpl).getPreUpdateNode().asExpr()] and
118+ // nodeTo = TSsaInputNode(next, input)
119+ // )
120+ // }
123121 /** Gets the SSA definition node corresponding to parameter `p`. */
124122 pragma [ nomagic]
125123 SsaDefinitionExtNode getParameterDefNode ( NamedParameter p ) {
@@ -139,14 +137,13 @@ module LocalFlow {
139137 nodeTo .getDefinitionExt ( ) = nodeFrom .( SelfParameterNodeImpl ) .getSelfDefinition ( )
140138 }
141139
142- /**
143- * Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
144- * involving SSA definition `def`.
145- */
146- predicate localSsaFlowStepUseUse ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
147- SsaImpl:: adjacentReadPairExt ( def , nodeFrom .asExpr ( ) , nodeTo .asExpr ( ) )
148- }
149-
140+ // /**
141+ // * Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
142+ // * involving SSA definition `def`.
143+ // */
144+ // predicate localSsaFlowStepUseUse(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
145+ // SsaImpl::adjacentReadPairExt(def, nodeFrom.asExpr(), nodeTo.asExpr())
146+ // }
150147 /**
151148 * Holds if SSA definition `def` assigns `value` to the underlying variable.
152149 *
@@ -173,33 +170,32 @@ module LocalFlow {
173170 )
174171 }
175172
176- /**
177- * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
178- * SSA definition `def`.
179- */
180- pragma [ nomagic]
181- predicate localSsaFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
182- // Flow from assignment into SSA definition
183- ssaDefAssigns ( def , nodeFrom .asExpr ( ) ) and
184- nodeTo .( SsaDefinitionExtNode ) .getDefinitionExt ( ) = def
185- or
186- // Flow from SSA definition to first read
187- def = nodeFrom .( SsaDefinitionExtNode ) .getDefinitionExt ( ) and
188- SsaImpl:: firstReadExt ( def , nodeTo .asExpr ( ) )
189- or
190- // Flow from post-update read to next read
191- localSsaFlowStepUseUse ( def , nodeFrom .( PostUpdateNodeImpl ) .getPreUpdateNode ( ) , nodeTo )
192- or
193- // Flow into phi (read) SSA definition node from def
194- localFlowSsaInputFromDef ( nodeFrom , def , nodeTo )
195- or
196- nodeTo .( SsaDefinitionExtNode ) .getDefinitionExt ( ) = def and
197- def = nodeFrom .( SsaInputNode ) .getDefinitionExt ( )
198- or
199- localFlowSsaParamInput ( nodeFrom , nodeTo ) and
200- def = nodeTo .( SsaDefinitionExtNode ) .getDefinitionExt ( )
201- }
202-
173+ // /**
174+ // * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
175+ // * SSA definition `def`.
176+ // */
177+ // pragma[nomagic]
178+ // predicate localSsaFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
179+ // // // Flow from assignment into SSA definition
180+ // // ssaDefAssigns(def, nodeFrom.asExpr()) and
181+ // // nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def
182+ // // or
183+ // // // Flow from SSA definition to first read
184+ // // def = nodeFrom.(SsaDefinitionExtNode).getDefinitionExt() and
185+ // // SsaImpl::firstReadExt(def, nodeTo.asExpr())
186+ // // or
187+ // // // Flow from post-update read to next read
188+ // // localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNodeImpl).getPreUpdateNode(), nodeTo)
189+ // // or
190+ // // // Flow into phi (read) SSA definition node from def
191+ // // localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
192+ // // or
193+ // // nodeTo.(SsaDefinitionExtNode).getDefinitionExt() = def and
194+ // // def = nodeFrom.(SsaInputNode).getDefinitionExt()
195+ // // or
196+ // localFlowSsaParamInput(nodeFrom, nodeTo) and
197+ // def = nodeTo.(SsaDefinitionExtNode).getDefinitionExt()
198+ // }
203199 pragma [ nomagic]
204200 predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
205201 nodeFrom .asExpr ( ) = nodeTo .asExpr ( ) .( CfgNodes:: ExprNodes:: BlockArgumentCfgNode ) .getValue ( )
@@ -338,6 +334,70 @@ predicate isNonConstantExpr(CfgNodes::ExprCfgNode n) {
338334 not n .getExpr ( ) instanceof ConstantAccess
339335}
340336
337+ private module SsaIntegration {
338+ private module Input implements SsaImpl:: Impl:: DataFlowIntegrationInputSig {
339+ private import ruby:: Ast as R
340+
341+ class Expr extends CfgNodes:: ExprCfgNode {
342+ predicate hasCfgNode ( SsaImpl:: SsaInput:: BasicBlock bb , int i ) { this = bb .getNode ( i ) }
343+
344+ predicate hasPostUpdateNode ( ) { this = any ( ExprPostUpdateNode n ) .getPreUpdateNode ( ) .asExpr ( ) }
345+ }
346+
347+ /**
348+ * Holds if SSA definition `def` assigns `value` to the underlying variable.
349+ *
350+ * This is either a direct assignment, `x = value`, or an assignment via
351+ * simple pattern matching
352+ *
353+ * ```rb
354+ * case value
355+ * in Foo => x then ...
356+ * in y => then ...
357+ * end
358+ * ```
359+ */
360+ predicate ssaDefAssigns ( SsaImpl:: WriteDefinition def , Expr value ) {
361+ def .( Ssa:: WriteDefinition ) .assigns ( value )
362+ or
363+ exists ( CfgNodes:: ExprNodes:: CaseExprCfgNode case , CfgNodes:: AstCfgNode pattern |
364+ case .getValue ( ) = value and
365+ pattern = case .getBranch ( _) .( CfgNodes:: ExprNodes:: InClauseCfgNode ) .getPattern ( )
366+ |
367+ def .( Ssa:: WriteDefinition ) .getWriteAccess ( ) =
368+ [ pattern , pattern .( CfgNodes:: ExprNodes:: AsPatternCfgNode ) .getVariableAccess ( ) ]
369+ )
370+ }
371+
372+ class Parameter = ParameterNodeImpl ;
373+
374+ predicate ssaDefInitializesParam ( SsaImpl:: WriteDefinition def , ParameterNodeImpl p ) {
375+ exists ( BasicBlock bb , int i |
376+ bb .getNode ( i ) .getAstNode ( ) = p .getParameter ( ) .( NamedParameter ) .getDefiningAccess ( ) and
377+ def .definesAt ( _, bb , i )
378+ )
379+ or
380+ def = p .( SelfParameterNodeImpl ) .getSelfDefinition ( )
381+ }
382+ }
383+
384+ module Impl = SsaImpl:: Impl:: DataFlowIntegration< Input > ;
385+
386+ private Impl:: Node asNode ( Node n ) {
387+ result = n .( SsaNode ) .getSsaNode ( )
388+ or
389+ result .( Impl:: ExprNode ) .getExpr ( ) = n .asExpr ( )
390+ or
391+ result .( Impl:: ExprPostUpdateNode ) .getExpr ( ) = n .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( )
392+ or
393+ result .( Impl:: ParameterNode ) .getParameter ( ) = n
394+ }
395+
396+ predicate localFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
397+ Impl:: localFlowStep ( def , asNode ( nodeFrom ) , asNode ( nodeTo ) )
398+ }
399+ }
400+
341401/** Provides logic related to captured variables. */
342402module VariableCapture {
343403 private import codeql.dataflow.VariableCapture as Shared
@@ -359,6 +419,8 @@ module VariableCapture {
359419
360420 class BasicBlock extends BasicBlocks:: BasicBlock {
361421 Callable getEnclosingCallable ( ) { result = this .getScope ( ) }
422+
423+ Location getLocation ( int i ) { result = this .getNode ( i ) .getLocation ( ) }
362424 }
363425
364426 BasicBlock getImmediateBasicBlockDominator ( BasicBlock bb ) {
@@ -537,10 +599,11 @@ private module Cached {
537599 newtype TNode =
538600 TExprNode ( CfgNodes:: ExprCfgNode n ) or
539601 TReturningNode ( CfgNodes:: ReturningCfgNode n ) { exists ( n .getReturnedValueNode ( ) ) } or
540- TSsaDefinitionExtNode ( SsaImpl:: DefinitionExt def ) or
541- TSsaInputNode ( SsaInputDefinitionExt def , BasicBlock input ) {
542- def .hasInputFromBlock ( _, _, _, input )
543- } or
602+ TSsaNode ( SsaIntegration:: Impl:: SsaNode node ) or
603+ // TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) or
604+ // TSsaInputNode(SsaInputDefinitionExt def, BasicBlock input) {
605+ // def.hasInputFromBlock(_, _, _, input)
606+ // } or
544607 TCapturedVariableNode ( VariableCapture:: CapturedVariable v ) or
545608 TNormalParameterNode ( Parameter p ) {
546609 p instanceof SimpleParameter or
@@ -621,13 +684,16 @@ private module Cached {
621684 // captured variables are handled by the shared `VariableCapture` library
622685 not def instanceof VariableCapture:: CapturedSsaDefinitionExt
623686 |
624- LocalFlow:: localSsaFlowStep ( def , nodeFrom , nodeTo )
625- or
626- LocalFlow:: localSsaFlowStepUseUse ( def , nodeFrom , nodeTo ) and
627- not FlowSummaryImpl:: Private:: Steps:: prohibitsUseUseFlow ( nodeFrom , _)
628- or
629- LocalFlow:: localFlowSsaInputFromRead ( def , nodeFrom , nodeTo ) and
687+ SsaIntegration:: localFlowStep ( def , nodeFrom , nodeTo ) and
630688 not FlowSummaryImpl:: Private:: Steps:: prohibitsUseUseFlow ( nodeFrom , _)
689+ // // SsaIntegration::Impl::localFlowStep(def, nodeFrom, nodeTo)
690+ // LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo)
691+ // or
692+ // LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
693+ // not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
694+ // or
695+ // LocalFlow::localFlowSsaInputFromRead(def, nodeFrom, nodeTo) and
696+ // not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
631697 )
632698 or
633699 VariableCapture:: valueStep ( nodeFrom , nodeTo )
@@ -642,10 +708,11 @@ private module Cached {
642708 predicate localFlowStepImpl ( Node nodeFrom , Node nodeTo ) {
643709 LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
644710 or
645- LocalFlow:: localSsaFlowStep ( _, nodeFrom , nodeTo )
646- or
647- LocalFlow:: localSsaFlowStepUseUse ( _, nodeFrom , nodeTo )
711+ // LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
712+ SsaIntegration:: localFlowStep ( _, nodeFrom , nodeTo )
648713 or
714+ // LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
715+ // or
649716 // Simple flow through library code is included in the exposed local
650717 // step relation, even though flow is technically inter-procedural
651718 FlowSummaryImpl:: Private:: Steps:: summaryThroughStepValue ( nodeFrom , nodeTo , _)
@@ -658,12 +725,13 @@ private module Cached {
658725 predicate localFlowStepTypeTracker ( Node nodeFrom , Node nodeTo ) {
659726 LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
660727 or
661- LocalFlow:: localSsaFlowStep ( _, nodeFrom , nodeTo )
662- or
663- LocalFlow:: localSsaFlowStepUseUse ( _, nodeFrom , nodeTo )
664- or
665- LocalFlow:: localFlowSsaInputFromRead ( _, nodeFrom , nodeTo )
728+ SsaIntegration:: localFlowStep ( _, nodeFrom , nodeTo )
666729 or
730+ // LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
731+ // or
732+ // LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
733+ // or
734+ // LocalFlow::localFlowSsaInputFromRead(_, nodeFrom, nodeTo)
667735 VariableCapture:: flowInsensitiveStep ( nodeFrom , nodeTo )
668736 or
669737 LocalFlow:: flowSummaryLocalStep ( nodeFrom , nodeTo , any ( LibraryCallableToIncludeInTypeTracking c ) ,
@@ -862,14 +930,28 @@ predicate nodeIsHidden(Node n) {
862930}
863931
864932/** An SSA definition, viewed as a node in a data flow graph. */
865- class SsaDefinitionExtNode extends NodeImpl , TSsaDefinitionExtNode {
933+ abstract class SsaNode extends NodeImpl , TSsaNode {
934+ SsaIntegration:: Impl:: SsaNode node ;
866935 SsaImpl:: DefinitionExt def ;
867936
868- SsaDefinitionExtNode ( ) { this = TSsaDefinitionExtNode ( def ) }
937+ SsaNode ( ) {
938+ this = TSsaNode ( node ) and
939+ def = node .getDefinitionExt ( )
940+ }
941+
942+ SsaIntegration:: Impl:: SsaNode getSsaNode ( ) { result = node }
869943
870- /** Gets the underlying SSA definition. */
871944 SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
872945
946+ override Location getLocationImpl ( ) { result = node .getLocation ( ) }
947+
948+ override string toStringImpl ( ) { result = node .toString ( ) }
949+ }
950+
951+ /** An SSA definition, viewed as a node in a data flow graph. */
952+ class SsaDefinitionExtNode extends SsaNode {
953+ override SsaIntegration:: Impl:: SsaDefinitionExtNode node ;
954+
873955 /** Gets the underlying variable. */
874956 Variable getVariable ( ) { result = def .getSourceVariable ( ) }
875957
@@ -881,10 +963,16 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
881963 }
882964
883965 override CfgScope getCfgScope ( ) { result = def .getBasicBlock ( ) .getScope ( ) }
966+ }
967+
968+ class SsaDefinitionNodeImpl extends SsaDefinitionExtNode {
969+ Ssa:: Definition ssaDef ;
884970
885- override Location getLocationImpl ( ) { result = def . getLocation ( ) }
971+ SsaDefinitionNodeImpl ( ) { ssaDef = def }
886972
887- override string toStringImpl ( ) { result = def .toString ( ) }
973+ override Location getLocationImpl ( ) { result = ssaDef .getLocation ( ) }
974+
975+ override string toStringImpl ( ) { result = ssaDef .toString ( ) }
888976}
889977
890978/**
@@ -922,20 +1010,20 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
9221010 *
9231011 * both inputs into the phi read node after the outer condition are guarded.
9241012 */
925- class SsaInputNode extends NodeImpl , TSsaInputNode {
926- SsaImpl :: DefinitionExt def ;
1013+ class SsaInputNode extends SsaNode {
1014+ override SsaIntegration :: Impl :: SsaInputNode node ;
9271015 BasicBlock input ;
9281016
929- SsaInputNode ( ) { this = TSsaInputNode ( def , input ) }
1017+ SsaInputNode ( ) { node . hasInputFromBlock ( def , input ) }
9301018
931- /** Gets the underlying SSA definition. */
932- SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
1019+ predicate isInputInto ( BasicBlock bb , SsaImpl:: DefinitionExt target ) {
1020+ bb = input and
1021+ target = def
1022+ }
9331023
9341024 override CfgScope getCfgScope ( ) { result = input .getScope ( ) }
935-
936- override Location getLocationImpl ( ) { result = input .getLastNode ( ) .getLocation ( ) }
937-
938- override string toStringImpl ( ) { result = "[input] " + def }
1025+ // override Location getLocationImpl() { result = input.getLastNode().getLocation() }
1026+ // override string toStringImpl() { result = "[input] " + def }
9391027}
9401028
9411029/** An SSA definition for a `self` variable. */
0 commit comments