@@ -87,39 +87,37 @@ class SsaInputDefinitionExt extends SsaImpl::DefinitionExt {
87
87
88
88
/** Provides predicates related to local data flow. */
89
89
module 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
+ // }
123
121
/** Gets the SSA definition node corresponding to parameter `p`. */
124
122
pragma [ nomagic]
125
123
SsaDefinitionExtNode getParameterDefNode ( NamedParameter p ) {
@@ -139,14 +137,13 @@ module LocalFlow {
139
137
nodeTo .getDefinitionExt ( ) = nodeFrom .( SelfParameterNodeImpl ) .getSelfDefinition ( )
140
138
}
141
139
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
+ // }
150
147
/**
151
148
* Holds if SSA definition `def` assigns `value` to the underlying variable.
152
149
*
@@ -173,33 +170,32 @@ module LocalFlow {
173
170
)
174
171
}
175
172
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
+ // }
203
199
pragma [ nomagic]
204
200
predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
205
201
nodeFrom .asExpr ( ) = nodeTo .asExpr ( ) .( CfgNodes:: ExprNodes:: BlockArgumentCfgNode ) .getValue ( )
@@ -338,6 +334,70 @@ predicate isNonConstantExpr(CfgNodes::ExprCfgNode n) {
338
334
not n .getExpr ( ) instanceof ConstantAccess
339
335
}
340
336
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
+
341
401
/** Provides logic related to captured variables. */
342
402
module VariableCapture {
343
403
private import codeql.dataflow.VariableCapture as Shared
@@ -359,6 +419,8 @@ module VariableCapture {
359
419
360
420
class BasicBlock extends BasicBlocks:: BasicBlock {
361
421
Callable getEnclosingCallable ( ) { result = this .getScope ( ) }
422
+
423
+ Location getLocation ( int i ) { result = this .getNode ( i ) .getLocation ( ) }
362
424
}
363
425
364
426
BasicBlock getImmediateBasicBlockDominator ( BasicBlock bb ) {
@@ -537,10 +599,11 @@ private module Cached {
537
599
newtype TNode =
538
600
TExprNode ( CfgNodes:: ExprCfgNode n ) or
539
601
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
544
607
TCapturedVariableNode ( VariableCapture:: CapturedVariable v ) or
545
608
TNormalParameterNode ( Parameter p ) {
546
609
p instanceof SimpleParameter or
@@ -621,13 +684,16 @@ private module Cached {
621
684
// captured variables are handled by the shared `VariableCapture` library
622
685
not def instanceof VariableCapture:: CapturedSsaDefinitionExt
623
686
|
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
630
688
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, _)
631
697
)
632
698
or
633
699
VariableCapture:: valueStep ( nodeFrom , nodeTo )
@@ -642,10 +708,11 @@ private module Cached {
642
708
predicate localFlowStepImpl ( Node nodeFrom , Node nodeTo ) {
643
709
LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
644
710
or
645
- LocalFlow:: localSsaFlowStep ( _, nodeFrom , nodeTo )
646
- or
647
- LocalFlow:: localSsaFlowStepUseUse ( _, nodeFrom , nodeTo )
711
+ // LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
712
+ SsaIntegration:: localFlowStep ( _, nodeFrom , nodeTo )
648
713
or
714
+ // LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
715
+ // or
649
716
// Simple flow through library code is included in the exposed local
650
717
// step relation, even though flow is technically inter-procedural
651
718
FlowSummaryImpl:: Private:: Steps:: summaryThroughStepValue ( nodeFrom , nodeTo , _)
@@ -658,12 +725,13 @@ private module Cached {
658
725
predicate localFlowStepTypeTracker ( Node nodeFrom , Node nodeTo ) {
659
726
LocalFlow:: localFlowStepCommon ( nodeFrom , nodeTo )
660
727
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 )
666
729
or
730
+ // LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
731
+ // or
732
+ // LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo)
733
+ // or
734
+ // LocalFlow::localFlowSsaInputFromRead(_, nodeFrom, nodeTo)
667
735
VariableCapture:: flowInsensitiveStep ( nodeFrom , nodeTo )
668
736
or
669
737
LocalFlow:: flowSummaryLocalStep ( nodeFrom , nodeTo , any ( LibraryCallableToIncludeInTypeTracking c ) ,
@@ -862,14 +930,28 @@ predicate nodeIsHidden(Node n) {
862
930
}
863
931
864
932
/** 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 ;
866
935
SsaImpl:: DefinitionExt def ;
867
936
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 }
869
943
870
- /** Gets the underlying SSA definition. */
871
944
SsaImpl:: DefinitionExt getDefinitionExt ( ) { result = def }
872
945
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
+
873
955
/** Gets the underlying variable. */
874
956
Variable getVariable ( ) { result = def .getSourceVariable ( ) }
875
957
@@ -881,10 +963,16 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
881
963
}
882
964
883
965
override CfgScope getCfgScope ( ) { result = def .getBasicBlock ( ) .getScope ( ) }
966
+ }
967
+
968
+ class SsaDefinitionNodeImpl extends SsaDefinitionExtNode {
969
+ Ssa:: Definition ssaDef ;
884
970
885
- override Location getLocationImpl ( ) { result = def . getLocation ( ) }
971
+ SsaDefinitionNodeImpl ( ) { ssaDef = def }
886
972
887
- override string toStringImpl ( ) { result = def .toString ( ) }
973
+ override Location getLocationImpl ( ) { result = ssaDef .getLocation ( ) }
974
+
975
+ override string toStringImpl ( ) { result = ssaDef .toString ( ) }
888
976
}
889
977
890
978
/**
@@ -922,20 +1010,20 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
922
1010
*
923
1011
* both inputs into the phi read node after the outer condition are guarded.
924
1012
*/
925
- class SsaInputNode extends NodeImpl , TSsaInputNode {
926
- SsaImpl :: DefinitionExt def ;
1013
+ class SsaInputNode extends SsaNode {
1014
+ override SsaIntegration :: Impl :: SsaInputNode node ;
927
1015
BasicBlock input ;
928
1016
929
- SsaInputNode ( ) { this = TSsaInputNode ( def , input ) }
1017
+ SsaInputNode ( ) { node . hasInputFromBlock ( def , input ) }
930
1018
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
+ }
933
1023
934
1024
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 }
939
1027
}
940
1028
941
1029
/** An SSA definition for a `self` variable. */
0 commit comments