@@ -171,7 +171,7 @@ module LocalFlow {
171171 * Either an SSA definition node for `def` when there is no read of `def`,
172172 * or a last read of `def`.
173173 */
174- predicate localFlowSsaInput ( Node nodeFrom , Ssa:: Definition def ) {
174+ private predicate localFlowSsaInput ( Node nodeFrom , Ssa:: Definition def ) {
175175 def = nodeFrom .( SsaDefinitionNode ) .getDefinition ( ) and
176176 not exists ( def .getARead ( ) )
177177 or
@@ -180,6 +180,51 @@ module LocalFlow {
180180 )
181181 }
182182
183+ /**
184+ * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
185+ * SSA definition `def.
186+ */
187+ predicate localSsaFlowStep ( Ssa:: Definition def , Node nodeFrom , Node nodeTo ) {
188+ // Flow from SSA definition to first read
189+ exists ( ControlFlow:: Node cfn |
190+ def = nodeFrom .( SsaDefinitionNode ) .getDefinition ( ) and
191+ nodeTo .asExprAtNode ( cfn ) = def .getAFirstReadAtNode ( cfn )
192+ )
193+ or
194+ // Flow from read to next read
195+ exists ( ControlFlow:: Node cfnFrom , ControlFlow:: Node cfnTo |
196+ Ssa:: Internal:: adjacentReadPairSameVar ( def , cfnFrom , cfnTo ) and
197+ nodeTo = TExprNode ( cfnTo )
198+ |
199+ nodeFrom = TExprNode ( cfnFrom )
200+ or
201+ cfnFrom = nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .getControlFlowNode ( )
202+ )
203+ or
204+ // Flow into SSA pseudo definition
205+ exists ( Ssa:: PseudoDefinition pseudo |
206+ localFlowSsaInput ( nodeFrom , def ) and
207+ pseudo = nodeTo .( SsaDefinitionNode ) .getDefinition ( ) and
208+ def = pseudo .getAnInput ( )
209+ )
210+ or
211+ // Flow into uncertain SSA definition
212+ exists ( LocalFlow:: UncertainExplicitSsaDefinition uncertain |
213+ localFlowSsaInput ( nodeFrom , def ) and
214+ uncertain = nodeTo .( SsaDefinitionNode ) .getDefinition ( ) and
215+ def = uncertain .getPriorDefinition ( )
216+ )
217+ }
218+
219+ /**
220+ * Holds if the source variable of SSA definition `def` is an instance field.
221+ */
222+ predicate usesInstanceField ( Ssa:: Definition def ) {
223+ exists ( Ssa:: SourceVariables:: FieldOrPropSourceVariable fp | fp = def .getSourceVariable ( ) |
224+ not fp .getAssignable ( ) .isStatic ( )
225+ )
226+ }
227+
183228 predicate localFlowCapturedVarStep ( SsaDefinitionNode nodeFrom , ImplicitCapturedArgumentNode nodeTo ) {
184229 // Flow from SSA definition to implicit captured variable argument
185230 exists ( Ssa:: ExplicitDefinition def , ControlFlow:: Nodes:: ElementNode call |
@@ -315,68 +360,43 @@ private module Cached {
315360 )
316361 }
317362
318- private predicate usesInstanceField ( Ssa:: Definition def ) {
319- exists ( Ssa:: SourceVariables:: FieldOrPropSourceVariable fp | fp = def .getSourceVariable ( ) |
320- not fp .getAssignable ( ) .isStatic ( )
321- )
322- }
323-
363+ /**
364+ * This is the local flow predicate that is used as a building block in global
365+ * data flow. It is a strict subset of the `localFlowStep` predicate, as it
366+ * excludes SSA flow through instance fields.
367+ */
324368 cached
325- predicate localFlowStepImpl ( Node nodeFrom , Node nodeTo , boolean simple ) {
326- any ( LocalFlow:: LocalExprStepConfiguration x ) .hasNodePath ( nodeFrom , nodeTo ) and
327- simple = true
328- or
329- // Flow from SSA definition to first read
330- exists ( Ssa:: Definition def , ControlFlow:: Node cfn |
331- def = nodeFrom .( SsaDefinitionNode ) .getDefinition ( ) and
332- nodeTo .asExprAtNode ( cfn ) = def .getAFirstReadAtNode ( cfn ) and
333- if usesInstanceField ( def ) then simple = false else simple = true
334- )
335- or
336- // Flow from read to next read
337- exists ( Ssa:: Definition def , ControlFlow:: Node cfnFrom , ControlFlow:: Node cfnTo |
338- Ssa:: Internal:: adjacentReadPairSameVar ( def , cfnFrom , cfnTo ) and
339- nodeTo = TExprNode ( cfnTo ) and
340- if usesInstanceField ( def ) then simple = false else simple = true
341- |
342- nodeFrom = TExprNode ( cfnFrom )
343- or
344- cfnFrom = nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) .getControlFlowNode ( )
369+ predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
370+ exists ( Ssa:: Definition def |
371+ LocalFlow:: localSsaFlowStep ( def , nodeFrom , nodeTo ) and
372+ not LocalFlow:: usesInstanceField ( def )
345373 )
346374 or
347- ThisFlow:: adjacentThisRefs ( nodeFrom , nodeTo ) and
348- simple = true
349- or
350- ThisFlow:: adjacentThisRefs ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) , nodeTo ) and
351- simple = true
375+ any ( LocalFlow:: LocalExprStepConfiguration x ) .hasNodePath ( nodeFrom , nodeTo )
352376 or
353- // Flow into SSA pseudo definition
354- exists ( Ssa:: Definition def , Ssa:: PseudoDefinition pseudo |
355- LocalFlow:: localFlowSsaInput ( nodeFrom , def ) and
356- pseudo = nodeTo .( SsaDefinitionNode ) .getDefinition ( ) and
357- def = pseudo .getAnInput ( ) and
358- if usesInstanceField ( def ) then simple = false else simple = true
359- )
377+ ThisFlow:: adjacentThisRefs ( nodeFrom , nodeTo )
360378 or
361- // Flow into uncertain SSA definition
362- exists ( Ssa:: Definition def , LocalFlow:: UncertainExplicitSsaDefinition uncertain |
363- LocalFlow:: localFlowSsaInput ( nodeFrom , def ) and
364- uncertain = nodeTo .( SsaDefinitionNode ) .getDefinition ( ) and
365- def = uncertain .getPriorDefinition ( ) and
366- if usesInstanceField ( def ) then simple = false else simple = true
367- )
379+ ThisFlow:: adjacentThisRefs ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) , nodeTo )
368380 or
369- LocalFlow:: localFlowCapturedVarStep ( nodeFrom , nodeTo ) and
370- simple = true
381+ LocalFlow:: localFlowCapturedVarStep ( nodeFrom , nodeTo )
371382 or
372- flowOutOfDelegateLibraryCall ( nodeFrom , nodeTo , true ) and
373- simple = true
383+ flowOutOfDelegateLibraryCall ( nodeFrom , nodeTo , true )
374384 or
375- flowThroughLibraryCallableOutRef ( _, nodeFrom , nodeTo , true ) and
376- simple = true
385+ flowThroughLibraryCallableOutRef ( _, nodeFrom , nodeTo , true )
377386 or
378- LocalFlow:: localFlowStepCil ( nodeFrom , nodeTo ) and
379- simple = true
387+ LocalFlow:: localFlowStepCil ( nodeFrom , nodeTo )
388+ }
389+
390+ /**
391+ * This is the extension of the predicate `simpleLocalFlowStep` that is exposed
392+ * as the `localFlowStep` predicate. It includes SSA flow through instance fields.
393+ */
394+ cached
395+ predicate extendedLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
396+ exists ( Ssa:: Definition def |
397+ LocalFlow:: localSsaFlowStep ( def , nodeFrom , nodeTo ) and
398+ LocalFlow:: usesInstanceField ( def )
399+ )
380400 }
381401
382402 /**
@@ -424,15 +444,6 @@ private module Cached {
424444}
425445import Cached
426446
427- /**
428- * This is the local flow predicate that is used as a building block in global
429- * data flow. It is a strict subset of the `localFlowStep` predicate, as it
430- * excludes SSA flow through instance fields.
431- */
432- predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
433- localFlowStepImpl ( nodeFrom , nodeTo , true )
434- }
435-
436447/** An SSA definition, viewed as a node in a data flow graph. */
437448class SsaDefinitionNode extends Node , TSsaDefinitionNode {
438449 Ssa:: Definition def ;
0 commit comments