@@ -12,6 +12,7 @@ private import semmle.code.java.dataflow.FlowSummary
12
12
private import semmle.code.java.dataflow.InstanceAccess
13
13
private import FlowSummaryImpl as FlowSummaryImpl
14
14
private import TaintTrackingUtil as TaintTrackingUtil
15
+ private import SsaImpl as SsaImpl
15
16
private import DataFlowNodes
16
17
import DataFlowNodes:: Public
17
18
@@ -99,6 +100,10 @@ predicate hasNonlocalValue(FieldRead fr) {
99
100
)
100
101
}
101
102
103
+ private predicate capturedVariableRead ( Node n ) {
104
+ n .asExpr ( ) .( VarRead ) .getVariable ( ) instanceof CapturedVariable
105
+ }
106
+
102
107
cached
103
108
private module Cached {
104
109
/**
@@ -108,7 +113,7 @@ private module Cached {
108
113
predicate localFlowStep ( Node node1 , Node node2 ) {
109
114
simpleLocalFlowStep0 ( node1 , node2 , _)
110
115
or
111
- adjacentUseUse ( node1 . asExpr ( ) , node2 . asExpr ( ) )
116
+ SsaFlow :: localFlowStep ( _ , node1 , node2 , _ )
112
117
or
113
118
// Simple flow through library code is included in the exposed local
114
119
// step relation, even though flow is technically inter-procedural
@@ -125,13 +130,31 @@ private module Cached {
125
130
predicate simpleLocalFlowStep ( Node node1 , Node node2 , string model ) {
126
131
simpleLocalFlowStep0 ( node1 , node2 , model )
127
132
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
128
146
any ( AdditionalValueStep a ) .step ( node1 , node2 ) and
129
147
pragma [ only_bind_out ] ( node1 .getEnclosingCallable ( ) ) =
130
148
pragma [ only_bind_out ] ( node2 .getEnclosingCallable ( ) ) and
131
149
model = "AdditionalValueStep" and
132
150
// prevent recursive call
133
151
( any ( AdditionalValueStep a ) .step ( _, _) implies any ( ) )
134
152
}
153
+
154
+ cached
155
+ Node getABarrierNode ( Guard guard , SsaVariable def , boolean branch ) {
156
+ SsaFlow:: asNode ( result ) = SsaImpl:: DataFlowIntegration:: getABarrierNode ( guard , def , branch )
157
+ }
135
158
}
136
159
137
160
/**
@@ -147,14 +170,7 @@ predicate localMustFlowStep(Node node1, Node node2) {
147
170
node2 .( ImplicitInstanceAccess ) .getInstanceAccess ( ) .( OwnInstanceAccess ) .getEnclosingCallable ( )
148
171
)
149
172
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 )
158
174
or
159
175
node2 .asExpr ( ) .( CastingExpr ) .getExpr ( ) = node1 .asExpr ( )
160
176
or
@@ -169,10 +185,6 @@ predicate localMustFlowStep(Node node1, Node node2) {
169
185
170
186
import Cached
171
187
172
- private predicate capturedVariableRead ( Node n ) {
173
- n .asExpr ( ) .( VarRead ) .getVariable ( ) instanceof CapturedVariable
174
- }
175
-
176
188
/**
177
189
* Holds if there is a data flow step from `e1` to `e2` that only steps from
178
190
* child to parent in the AST.
@@ -214,34 +226,8 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
214
226
private predicate simpleLocalFlowStep0 ( Node node1 , Node node2 , string model ) {
215
227
(
216
228
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
240
229
ThisFlow:: adjacentThisRefs ( node1 , node2 )
241
230
or
242
- adjacentUseUse ( node1 .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) , node2 .asExpr ( ) ) and
243
- not capturedVariableRead ( node2 )
244
- or
245
231
ThisFlow:: adjacentThisRefs ( node1 .( PostUpdateNode ) .getPreUpdateNode ( ) , node2 )
246
232
or
247
233
simpleAstFlowStep ( node1 .asExpr ( ) , node2 .asExpr ( ) )
@@ -401,13 +387,16 @@ signature predicate guardChecksSig(Guard g, Expr e, boolean branch);
401
387
* in data flow and taint tracking.
402
388
*/
403
389
module 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
+
404
395
/** Gets a node that is safely guarded by the given guard check. */
405
396
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 )
411
400
)
412
401
}
413
402
}
0 commit comments