@@ -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,6 +130,19 @@ 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
@@ -147,14 +165,7 @@ predicate localMustFlowStep(Node node1, Node node2) {
147165 node2 .( ImplicitInstanceAccess ) .getInstanceAccess ( ) .( OwnInstanceAccess ) .getEnclosingCallable ( )
148166 )
149167 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- )
168+ SsaFlow:: localMustFlowStep ( _, node1 , node2 )
158169 or
159170 node2 .asExpr ( ) .( CastingExpr ) .getExpr ( ) = node1 .asExpr ( )
160171 or
@@ -169,10 +180,6 @@ predicate localMustFlowStep(Node node1, Node node2) {
169180
170181import Cached
171182
172- private predicate capturedVariableRead ( Node n ) {
173- n .asExpr ( ) .( VarRead ) .getVariable ( ) instanceof CapturedVariable
174- }
175-
176183/**
177184 * Holds if there is a data flow step from `e1` to `e2` that only steps from
178185 * child to parent in the AST.
@@ -214,34 +221,8 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
214221private predicate simpleLocalFlowStep0 ( Node node1 , Node node2 , string model ) {
215222 (
216223 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
240224 ThisFlow:: adjacentThisRefs ( node1 , node2 )
241225 or
242- adjacentUseUse ( node1 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) , node2 .asExpr ( ) ) and
243- not capturedVariableRead ( node2 )
244- or
245226 ThisFlow:: adjacentThisRefs ( node1 .( PostUpdateNode ) .getPreUpdateNode ( ) , node2 )
246227 or
247228 simpleAstFlowStep ( node1 .asExpr ( ) , node2 .asExpr ( ) )
@@ -401,13 +382,16 @@ signature predicate guardChecksSig(Guard g, Expr e, boolean branch);
401382 * in data flow and taint tracking.
402383 */
403384module BarrierGuard< guardChecksSig / 3 guardChecks> {
385+ pragma [ nomagic]
386+ private predicate guardChecksSsaDef ( Guard g , SsaVariable v , boolean branch ) {
387+ guardChecks ( g , v .getAUse ( ) , branch )
388+ }
389+
404390 /** Gets a node that is safely guarded by the given guard check. */
405391 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
392+ exists ( Guard g , SsaVariable v , boolean branch |
393+ guardChecksSsaDef ( g , v , branch ) and
394+ result = getABarrierNode ( g , v , branch )
411395 )
412396 }
413397}
0 commit comments