@@ -12,6 +12,7 @@ private import semmle.code.java.dataflow.FlowSummary
1212private import semmle.code.java.dataflow.InstanceAccess
1313private import FlowSummaryImpl as FlowSummaryImpl
1414private import TaintTrackingUtil as TaintTrackingUtil
15+ private import SsaImpl as SsaImpl
1516private import DataFlowNodes
1617import DataFlowNodes:: Public
1718
@@ -99,6 +100,10 @@ predicate hasNonlocalValue(FieldRead fr) {
99100 )
100101}
101102
103+ private predicate capturedVariableRead ( Node n ) {
104+ n .asExpr ( ) .( VarRead ) .getVariable ( ) instanceof CapturedVariable
105+ }
106+
102107cached
103108private module Cached {
104109 /**
@@ -108,7 +113,7 @@ private module Cached {
108113 predicate localFlowStep ( Node node1 , Node node2 ) {
109114 simpleLocalFlowStep0 ( node1 , node2 , _)
110115 or
111- adjacentUseUse ( node1 . asExpr ( ) , node2 . asExpr ( ) )
116+ SsaFlow :: localFlowStep ( _ , node1 , node2 , _ )
112117 or
113118 // Simple flow through library code is included in the exposed local
114119 // step relation, even though flow is technically inter-procedural
@@ -125,13 +130,31 @@ private module Cached {
125130 predicate simpleLocalFlowStep ( Node node1 , Node node2 , string model ) {
126131 simpleLocalFlowStep0 ( node1 , node2 , model )
127132 or
133+ exists ( boolean isUseStep |
134+ SsaFlow:: localFlowStep ( _, node1 , node2 , isUseStep ) and
135+ not capturedVariableRead ( node2 ) and
136+ model = ""
137+ |
138+ isUseStep = false
139+ or
140+ not exists ( FieldRead fr |
141+ hasNonlocalValue ( fr ) and fr .getField ( ) .isStatic ( ) and fr = node1 .asExpr ( )
142+ ) and
143+ not FlowSummaryImpl:: Private:: Steps:: prohibitsUseUseFlow ( node1 , _)
144+ )
145+ or
128146 any ( AdditionalValueStep a ) .step ( node1 , node2 ) and
129147 pragma [ only_bind_out ] ( node1 .getEnclosingCallable ( ) ) =
130148 pragma [ only_bind_out ] ( node2 .getEnclosingCallable ( ) ) and
131149 model = "AdditionalValueStep" and
132150 // prevent recursive call
133151 ( any ( AdditionalValueStep a ) .step ( _, _) implies any ( ) )
134152 }
153+
154+ cached
155+ Node getABarrierNode ( Guard guard , SsaVariable def , boolean branch ) {
156+ SsaFlow:: asNode ( result ) = SsaImpl:: DataFlowIntegration:: getABarrierNode ( guard , def , branch )
157+ }
135158}
136159
137160/**
@@ -147,14 +170,7 @@ predicate localMustFlowStep(Node node1, Node node2) {
147170 node2 .( ImplicitInstanceAccess ) .getInstanceAccess ( ) .( OwnInstanceAccess ) .getEnclosingCallable ( )
148171 )
149172 or
150- exists ( SsaImplicitInit init |
151- init .isParameterDefinition ( node1 .asParameter ( ) ) and init .getAUse ( ) = node2 .asExpr ( )
152- )
153- or
154- exists ( SsaExplicitUpdate upd |
155- upd .getDefiningExpr ( ) .( VariableAssign ) .getSource ( ) = node1 .asExpr ( ) and
156- upd .getAUse ( ) = node2 .asExpr ( )
157- )
173+ SsaFlow:: localMustFlowStep ( _, node1 , node2 )
158174 or
159175 node2 .asExpr ( ) .( CastingExpr ) .getExpr ( ) = node1 .asExpr ( )
160176 or
@@ -169,10 +185,6 @@ predicate localMustFlowStep(Node node1, Node node2) {
169185
170186import Cached
171187
172- private predicate capturedVariableRead ( Node n ) {
173- n .asExpr ( ) .( VarRead ) .getVariable ( ) instanceof CapturedVariable
174- }
175-
176188/**
177189 * Holds if there is a data flow step from `e1` to `e2` that only steps from
178190 * child to parent in the AST.
@@ -214,34 +226,8 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
214226private predicate simpleLocalFlowStep0 ( Node node1 , Node node2 , string model ) {
215227 (
216228 TaintTrackingUtil:: forceCachingInSameStage ( ) and
217- // Variable flow steps through adjacent def-use and use-use pairs.
218- exists ( SsaExplicitUpdate upd |
219- upd .getDefiningExpr ( ) .( VariableAssign ) .getSource ( ) = node1 .asExpr ( ) or
220- upd .getDefiningExpr ( ) .( AssignOp ) = node1 .asExpr ( ) or
221- upd .getDefiningExpr ( ) .( RecordBindingVariableExpr ) = node1 .asExpr ( )
222- |
223- node2 .asExpr ( ) = upd .getAFirstUse ( ) and
224- not capturedVariableRead ( node2 )
225- )
226- or
227- exists ( SsaImplicitInit init |
228- init .isParameterDefinition ( node1 .asParameter ( ) ) and
229- node2 .asExpr ( ) = init .getAFirstUse ( ) and
230- not capturedVariableRead ( node2 )
231- )
232- or
233- adjacentUseUse ( node1 .asExpr ( ) , node2 .asExpr ( ) ) and
234- not exists ( FieldRead fr |
235- hasNonlocalValue ( fr ) and fr .getField ( ) .isStatic ( ) and fr = node1 .asExpr ( )
236- ) and
237- not FlowSummaryImpl:: Private:: Steps:: prohibitsUseUseFlow ( node1 , _) and
238- not capturedVariableRead ( node2 )
239- or
240229 ThisFlow:: adjacentThisRefs ( node1 , node2 )
241230 or
242- adjacentUseUse ( node1 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) , node2 .asExpr ( ) ) and
243- not capturedVariableRead ( node2 )
244- or
245231 ThisFlow:: adjacentThisRefs ( node1 .( PostUpdateNode ) .getPreUpdateNode ( ) , node2 )
246232 or
247233 simpleAstFlowStep ( node1 .asExpr ( ) , node2 .asExpr ( ) )
@@ -401,13 +387,16 @@ signature predicate guardChecksSig(Guard g, Expr e, boolean branch);
401387 * in data flow and taint tracking.
402388 */
403389module BarrierGuard< guardChecksSig / 3 guardChecks> {
390+ pragma [ nomagic]
391+ private predicate guardChecksSsaDef ( Guard g , SsaVariable v , boolean branch ) {
392+ guardChecks ( g , v .getAUse ( ) , branch )
393+ }
394+
404395 /** Gets a node that is safely guarded by the given guard check. */
405396 Node getABarrierNode ( ) {
406- exists ( Guard g , SsaVariable v , boolean branch , VarRead use |
407- guardChecks ( g , v .getAUse ( ) , branch ) and
408- use = v .getAUse ( ) and
409- g .controls ( use .getBasicBlock ( ) , branch ) and
410- result .asExpr ( ) = use
397+ exists ( Guard g , SsaVariable v , boolean branch |
398+ guardChecksSsaDef ( g , v , branch ) and
399+ result = getABarrierNode ( g , v , branch )
411400 )
412401 }
413402}
0 commit comments