@@ -2,6 +2,7 @@ private import codeql.ssa.Ssa as SsaImplCommon
22private import codeql.ruby.AST
33private import codeql.ruby.CFG as Cfg
44private import codeql.ruby.controlflow.internal.ControlFlowGraphImplShared as ControlFlowGraphImplShared
5+ private import codeql.ruby.dataflow.SSA
56private import codeql.ruby.ast.Variable
67private import Cfg:: CfgNodes:: ExprNodes
78
@@ -61,7 +62,23 @@ private module SsaInput implements SsaImplCommon::InputSig {
6162 }
6263}
6364
64- import SsaImplCommon:: Make< SsaInput >
65+ private import SsaImplCommon:: Make< SsaInput > as Impl
66+
67+ class Definition = Impl:: Definition ;
68+
69+ class WriteDefinition = Impl:: WriteDefinition ;
70+
71+ class UncertainWriteDefinition = Impl:: UncertainWriteDefinition ;
72+
73+ class PhiNode = Impl:: PhiNode ;
74+
75+ module Consistency = Impl:: Consistency;
76+
77+ module ExposedForTestingOnly {
78+ predicate ssaDefReachesReadExt = Impl:: ssaDefReachesReadExt / 4 ;
79+
80+ predicate phiHasInputFromBlockExt = Impl:: phiHasInputFromBlockExt / 3 ;
81+ }
6582
6683/** Holds if `v` is uninitialized at index `i` in entry block `bb`. */
6784predicate uninitializedWrite ( Cfg:: EntryBasicBlock bb , int i , LocalVariable v ) {
@@ -204,7 +221,7 @@ private predicate adjacentDefRead(
204221 Definition def , SsaInput:: BasicBlock bb1 , int i1 , SsaInput:: BasicBlock bb2 , int i2 ,
205222 SsaInput:: SourceVariable v
206223) {
207- adjacentDefRead ( def , bb1 , i1 , bb2 , i2 ) and
224+ Impl :: adjacentDefRead ( def , bb1 , i1 , bb2 , i2 ) and
208225 v = def .getSourceVariable ( )
209226}
210227
@@ -220,7 +237,7 @@ private predicate adjacentDefReachesRead(
220237 exists ( SsaInput:: BasicBlock bb3 , int i3 |
221238 adjacentDefReachesRead ( def , bb1 , i1 , bb3 , i3 ) and
222239 SsaInput:: variableRead ( bb3 , i3 , _, false ) and
223- adjacentDefRead ( def , bb3 , i3 , bb2 , i2 )
240+ Impl :: adjacentDefRead ( def , bb3 , i3 , bb2 , i2 )
224241 )
225242}
226243
@@ -243,11 +260,11 @@ private predicate adjacentDefReachesUncertainRead(
243260/** Same as `lastRefRedef`, but skips uncertain reads. */
244261pragma [ nomagic]
245262private predicate lastRefSkipUncertainReads ( Definition def , SsaInput:: BasicBlock bb , int i ) {
246- lastRef ( def , bb , i ) and
263+ Impl :: lastRef ( def , bb , i ) and
247264 not SsaInput:: variableRead ( bb , i , def .getSourceVariable ( ) , false )
248265 or
249266 exists ( SsaInput:: BasicBlock bb0 , int i0 |
250- lastRef ( def , bb0 , i0 ) and
267+ Impl :: lastRef ( def , bb0 , i0 ) and
251268 adjacentDefReachesUncertainRead ( def , bb , i , bb0 , i0 )
252269 )
253270}
@@ -304,7 +321,7 @@ private module Cached {
304321 cached
305322 VariableReadAccessCfgNode getARead ( Definition def ) {
306323 exists ( LocalVariable v , Cfg:: BasicBlock bb , int i |
307- ssaDefReachesRead ( v , def , bb , i ) and
324+ Impl :: ssaDefReachesRead ( v , def , bb , i ) and
308325 variableReadActual ( bb , i , v ) and
309326 result = bb .getNode ( i )
310327 )
@@ -315,7 +332,7 @@ private module Cached {
315332 Definition def , CallCfgNode call , LocalVariable v , Cfg:: CfgScope scope
316333 ) {
317334 exists ( Cfg:: BasicBlock bb , int i |
318- ssaDefReachesRead ( v , def , bb , i ) and
335+ Impl :: ssaDefReachesRead ( v , def , bb , i ) and
319336 capturedCallRead ( call , bb , i , v ) and
320337 scope .getOuterCfgScope ( ) = bb .getScope ( )
321338 )
@@ -360,7 +377,7 @@ private module Cached {
360377 Definition def , LocalVariable v , Cfg:: CfgScope scope
361378 ) {
362379 exists ( Cfg:: BasicBlock bb , int i |
363- ssaDefReachesRead ( v , def , bb , i ) and
380+ Impl :: ssaDefReachesRead ( v , def , bb , i ) and
364381 capturedExitRead ( bb , i , v ) and
365382 scope = bb .getScope ( ) .getOuterCfgScope * ( )
366383 )
@@ -403,7 +420,7 @@ private module Cached {
403420
404421 cached
405422 Definition phiHasInputFromBlock ( PhiNode phi , Cfg:: BasicBlock bb ) {
406- phiHasInputFromBlock ( phi , result , bb )
423+ Impl :: phiHasInputFromBlock ( phi , result , bb )
407424 }
408425
409426 /**
@@ -459,19 +476,45 @@ private module Cached {
459476 */
460477 cached
461478 predicate lastRefBeforeRedef ( Definition def , Cfg:: BasicBlock bb , int i , Definition next ) {
462- lastRefRedef ( def , bb , i , next ) and
479+ Impl :: lastRefRedef ( def , bb , i , next ) and
463480 not SsaInput:: variableRead ( bb , i , def .getSourceVariable ( ) , false )
464481 or
465482 exists ( SsaInput:: BasicBlock bb0 , int i0 |
466- lastRefRedef ( def , bb0 , i0 , next ) and
483+ Impl :: lastRefRedef ( def , bb0 , i0 , next ) and
467484 adjacentDefReachesUncertainRead ( def , bb , i , bb0 , i0 )
468485 )
469486 }
470487
471488 cached
472489 Definition uncertainWriteDefinitionInput ( UncertainWriteDefinition def ) {
473- uncertainWriteDefinitionInput ( def , result )
490+ Impl :: uncertainWriteDefinitionInput ( def , result )
474491 }
475492}
476493
477494import Cached
495+
496+ /**
497+ * An extended static single assignment (SSA) definition.
498+ *
499+ * This is either a normal SSA definition (`Definition`) or a
500+ * phi-read node (`PhiReadNode`).
501+ *
502+ * Only intended for internal use.
503+ */
504+ class DefinitionExt extends Impl:: DefinitionExt {
505+ override string toString ( ) { result = this .( Ssa:: Definition ) .toString ( ) }
506+
507+ /** Gets the location of this definition. */
508+ Location getLocation ( ) { result = this .( Ssa:: Definition ) .getLocation ( ) }
509+ }
510+
511+ /**
512+ * A phi-read node.
513+ *
514+ * Only intended for internal use.
515+ */
516+ class PhiReadNode extends DefinitionExt , Impl:: PhiReadNode {
517+ override string toString ( ) { result = "SSA phi read(" + this .getSourceVariable ( ) + ")" }
518+
519+ override Location getLocation ( ) { result = this .getBasicBlock ( ) .getLocation ( ) }
520+ }
0 commit comments