@@ -908,19 +908,20 @@ private class Argument extends Expr {
908
908
*
909
909
* `postUpdate` indicates whether the store targets a post-update node.
910
910
*/
911
- private predicate fieldOrPropertyStore ( Expr e , Content c , Expr src , Expr q , boolean postUpdate ) {
911
+ private predicate fieldOrPropertyStore ( Expr e , ContentSet c , Expr src , Expr q , boolean postUpdate ) {
912
912
exists ( FieldOrProperty f |
913
- c = f .getContent ( ) and
913
+ c = f .getContentSet ( ) and
914
914
(
915
915
f .isFieldLike ( ) and
916
916
f instanceof InstanceFieldOrProperty
917
917
or
918
918
exists (
919
919
FlowSummaryImpl:: Private:: SummarizedCallableImpl sc ,
920
- FlowSummaryImpl:: Private:: SummaryComponentStack input
920
+ FlowSummaryImpl:: Private:: SummaryComponentStack input , ContentSet readSet
921
921
|
922
922
sc .propagatesFlow ( input , _, _, _) and
923
- input .contains ( FlowSummaryImpl:: Private:: SummaryComponent:: content ( f .getContent ( ) ) )
923
+ input .contains ( FlowSummaryImpl:: Private:: SummaryComponent:: content ( readSet ) ) and
924
+ c .getAStoreContent ( ) = readSet .getAReadContent ( )
924
925
)
925
926
)
926
927
|
@@ -970,28 +971,13 @@ private predicate fieldOrPropertyStore(Expr e, Content c, Expr src, Expr q, bool
970
971
)
971
972
}
972
973
973
- /** Holds if property `p1` overrides or implements source declaration property `p2`. */
974
- private predicate overridesOrImplementsSourceDecl ( Property p1 , Property p2 ) {
975
- p1 .getOverridee * ( ) .getUnboundDeclaration ( ) = p2
976
- or
977
- p1 .getAnUltimateImplementee ( ) .getUnboundDeclaration ( ) = p2
978
- }
979
-
980
974
/**
981
975
* Holds if `e2` is an expression that reads field or property `c` from
982
- * expression `e1`. This takes overriding into account for properties written
983
- * from library code.
976
+ * expression `e1`.
984
977
*/
985
- private predicate fieldOrPropertyRead ( Expr e1 , Content c , FieldOrPropertyRead e2 ) {
978
+ private predicate fieldOrPropertyRead ( Expr e1 , ContentSet c , FieldOrPropertyRead e2 ) {
986
979
e1 = e2 .getQualifier ( ) and
987
- exists ( FieldOrProperty ret | c = ret .getContent ( ) |
988
- ret = e2 .getTarget ( )
989
- or
990
- exists ( Property target |
991
- target .getGetter ( ) = e2 .( PropertyCall ) .getARuntimeTarget ( ) and
992
- overridesOrImplementsSourceDecl ( target , ret )
993
- )
994
- )
980
+ c = e2 .getTarget ( ) .( FieldOrProperty ) .getContentSet ( )
995
981
}
996
982
997
983
/**
@@ -1208,6 +1194,11 @@ private module Cached {
1208
1194
} or
1209
1195
TCapturedVariableContent ( VariableCapture:: CapturedVariable v )
1210
1196
1197
+ cached
1198
+ newtype TContentSet =
1199
+ TSingletonContent ( Content c ) { not c instanceof PropertyContent } or
1200
+ TPropertyContentSet ( Property p ) { p .isUnboundDeclaration ( ) }
1201
+
1211
1202
cached
1212
1203
newtype TContentApprox =
1213
1204
TFieldApproxContent ( string firstChar ) { firstChar = approximateFieldContent ( _) } or
@@ -2076,10 +2067,10 @@ class FieldOrProperty extends Assignable, Modifiable {
2076
2067
}
2077
2068
2078
2069
/** Gets the content that matches this field or property. */
2079
- Content getContent ( ) {
2080
- result .( FieldContent ) . getField ( ) = this .getUnboundDeclaration ( )
2070
+ ContentSet getContentSet ( ) {
2071
+ result .isField ( this .getUnboundDeclaration ( ) )
2081
2072
or
2082
- result .( PropertyContent ) . getProperty ( ) = this .getUnboundDeclaration ( )
2073
+ result .isProperty ( this .getUnboundDeclaration ( ) )
2083
2074
}
2084
2075
}
2085
2076
@@ -2211,8 +2202,8 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
2211
2202
}
2212
2203
2213
2204
pragma [ nomagic]
2214
- private PropertyContent getResultContent ( ) {
2215
- result .getProperty ( ) = any ( SystemThreadingTasksTaskTClass c_ ) .getResultProperty ( )
2205
+ private ContentSet getResultContent ( ) {
2206
+ result .isProperty ( any ( SystemThreadingTasksTaskTClass c_ ) .getResultProperty ( ) )
2216
2207
}
2217
2208
2218
2209
private predicate primaryConstructorParameterStore (
@@ -2226,17 +2217,16 @@ private predicate primaryConstructorParameterStore(
2226
2217
)
2227
2218
}
2228
2219
2229
- /**
2230
- * Holds if data can flow from `node1` to `node2` via an assignment to
2231
- * content `c`.
2232
- */
2233
- predicate storeStep ( Node node1 , ContentSet c , Node node2 ) {
2220
+ pragma [ nomagic]
2221
+ private predicate recordParameter ( RecordType t , Parameter p , string name ) {
2222
+ p .getName ( ) = name and p .getCallable ( ) .getDeclaringType ( ) = t
2223
+ }
2224
+
2225
+ private predicate storeContentStep ( Node node1 , Content c , Node node2 ) {
2234
2226
exists ( StoreStepConfiguration x , ExprNode node , boolean postUpdate |
2235
2227
hasNodePath ( x , node1 , node ) and
2236
2228
if postUpdate = true then node = node2 .( PostUpdateNode ) .getPreUpdateNode ( ) else node = node2
2237
2229
|
2238
- fieldOrPropertyStore ( _, c , node1 .asExpr ( ) , node .getExpr ( ) , postUpdate )
2239
- or
2240
2230
arrayStore ( _, node1 .asExpr ( ) , node .getExpr ( ) , postUpdate ) and c instanceof ElementContent
2241
2231
)
2242
2232
or
@@ -2257,26 +2247,59 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
2257
2247
c instanceof ElementContent
2258
2248
)
2259
2249
or
2250
+ primaryConstructorParameterStore ( node1 , c , node2 )
2251
+ or
2252
+ exists ( Parameter p , DataFlowCallable callable |
2253
+ node1 = TExplicitParameterNode ( p , callable ) and
2254
+ node2 = TPrimaryConstructorThisAccessNode ( p , true , callable ) and
2255
+ not recordParameter ( _, p , _) and
2256
+ c .( PrimaryConstructorParameterContent ) .getParameter ( ) = p
2257
+ )
2258
+ or
2259
+ VariableCapture:: storeStep ( node1 , c , node2 )
2260
+ }
2261
+
2262
+ pragma [ nomagic]
2263
+ private predicate recordProperty ( RecordType t , ContentSet c , string name ) {
2264
+ exists ( Property p |
2265
+ c .isProperty ( p ) and
2266
+ p .getName ( ) = name and
2267
+ p .getDeclaringType ( ) = t
2268
+ )
2269
+ }
2270
+
2271
+ /**
2272
+ * Holds if data can flow from `node1` to `node2` via an assignment to
2273
+ * content `c`.
2274
+ */
2275
+ predicate storeStep ( Node node1 , ContentSet c , Node node2 ) {
2276
+ exists ( Content cont |
2277
+ storeContentStep ( node1 , cont , node2 ) and
2278
+ c .isSingleton ( cont )
2279
+ )
2280
+ or
2281
+ exists ( StoreStepConfiguration x , ExprNode node , boolean postUpdate |
2282
+ hasNodePath ( x , node1 , node ) and
2283
+ if postUpdate = true then node = node2 .( PostUpdateNode ) .getPreUpdateNode ( ) else node = node2
2284
+ |
2285
+ fieldOrPropertyStore ( _, c , node1 .asExpr ( ) , node .getExpr ( ) , postUpdate )
2286
+ )
2287
+ or
2260
2288
exists ( Expr e |
2261
2289
e = node1 .asExpr ( ) and
2262
2290
node2 .( AsyncReturnNode ) .getExpr ( ) = e and
2263
2291
c = getResultContent ( )
2264
2292
)
2265
2293
or
2266
- primaryConstructorParameterStore ( node1 , c , node2 )
2267
- or
2268
- exists ( Parameter p , DataFlowCallable callable |
2294
+ exists ( Parameter p , DataFlowCallable callable , RecordType t , string name |
2269
2295
node1 = TExplicitParameterNode ( p , callable ) and
2270
2296
node2 = TPrimaryConstructorThisAccessNode ( p , true , callable ) and
2271
- if p .getCallable ( ) .getDeclaringType ( ) instanceof RecordType
2272
- then c .( PropertyContent ) .getProperty ( ) .getName ( ) = p .getName ( )
2273
- else c .( PrimaryConstructorParameterContent ) .getParameter ( ) = p
2297
+ recordParameter ( t , p , name ) and
2298
+ recordProperty ( t , c , name )
2274
2299
)
2275
2300
or
2276
2301
FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
2277
2302
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2278
- or
2279
- VariableCapture:: storeStep ( node1 , c , node2 )
2280
2303
}
2281
2304
2282
2305
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -2344,14 +2367,8 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
2344
2367
}
2345
2368
}
2346
2369
2347
- /**
2348
- * Holds if data can flow from `node1` to `node2` via a read of content `c`.
2349
- */
2350
- predicate readStep ( Node node1 , ContentSet c , Node node2 ) {
2370
+ private predicate readContentStep ( Node node1 , Content c , Node node2 ) {
2351
2371
exists ( ReadStepConfiguration x |
2352
- hasNodePath ( x , node1 , node2 ) and
2353
- fieldOrPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2354
- or
2355
2372
hasNodePath ( x , node1 , node2 ) and
2356
2373
arrayRead ( node1 .asExpr ( ) , node2 .asExpr ( ) ) and
2357
2374
c instanceof ElementContent
@@ -2363,10 +2380,6 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2363
2380
c instanceof ElementContent
2364
2381
)
2365
2382
or
2366
- hasNodePath ( x , node1 , node2 ) and
2367
- node2 .asExpr ( ) .( AwaitExpr ) .getExpr ( ) = node1 .asExpr ( ) and
2368
- c = getResultContent ( )
2369
- or
2370
2383
node1 =
2371
2384
any ( InstanceParameterAccessPreNode n |
2372
2385
n .getUnderlyingControlFlowNode ( ) = node2 .( ExprNode ) .getControlFlowNode ( ) and
@@ -2404,10 +2417,41 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2404
2417
)
2405
2418
)
2406
2419
or
2420
+ VariableCapture:: readStep ( node1 , c , node2 )
2421
+ }
2422
+
2423
+ /**
2424
+ * Holds if data can flow from `node1` to `node2` via a read of content `c`.
2425
+ */
2426
+ predicate readStep ( Node node1 , ContentSet c , Node node2 ) {
2427
+ exists ( Content cont |
2428
+ readContentStep ( node1 , cont , node2 ) and
2429
+ c .isSingleton ( cont )
2430
+ )
2431
+ or
2432
+ exists ( ReadStepConfiguration x | hasNodePath ( x , node1 , node2 ) |
2433
+ fieldOrPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2434
+ or
2435
+ node2 .asExpr ( ) .( AwaitExpr ) .getExpr ( ) = node1 .asExpr ( ) and
2436
+ c = getResultContent ( )
2437
+ )
2438
+ or
2407
2439
FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
2408
2440
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2441
+ }
2442
+
2443
+ private predicate clearsCont ( Node n , Content c ) {
2444
+ exists ( Argument a , Struct s , Field f |
2445
+ a = n .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) and
2446
+ a .getType ( ) = s and
2447
+ f = s .getAField ( ) and
2448
+ c .( FieldContent ) .getField ( ) = f .getUnboundDeclaration ( ) and
2449
+ not f .isRef ( )
2450
+ )
2409
2451
or
2410
- VariableCapture:: readStep ( node1 , c , node2 )
2452
+ n = any ( PostUpdateNode n1 | primaryConstructorParameterStore ( _, c , n1 ) ) .getPreUpdateNode ( )
2453
+ or
2454
+ VariableCapture:: clearsContent ( n , c )
2411
2455
}
2412
2456
2413
2457
/**
@@ -2416,6 +2460,11 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2416
2460
* in `x.f = newValue`.
2417
2461
*/
2418
2462
predicate clearsContent ( Node n , ContentSet c ) {
2463
+ exists ( Content cont |
2464
+ clearsCont ( n , cont ) and
2465
+ c .isSingleton ( cont )
2466
+ )
2467
+ or
2419
2468
fieldOrPropertyStore ( _, c , _, n .asExpr ( ) , true )
2420
2469
or
2421
2470
fieldOrPropertyStore ( _, c , _, n .( ObjectInitializerNode ) .getInitializer ( ) , false )
@@ -2426,20 +2475,8 @@ predicate clearsContent(Node n, ContentSet c) {
2426
2475
oi = we .getInitializer ( ) and
2427
2476
n .asExpr ( ) = oi and
2428
2477
f = oi .getAMemberInitializer ( ) .getInitializedMember ( ) and
2429
- c = f .getContent ( )
2430
- )
2431
- or
2432
- exists ( Argument a , Struct s , Field f |
2433
- a = n .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) and
2434
- a .getType ( ) = s and
2435
- f = s .getAField ( ) and
2436
- c .( FieldContent ) .getField ( ) = f .getUnboundDeclaration ( ) and
2437
- not f .isRef ( )
2478
+ c = f .getContentSet ( )
2438
2479
)
2439
- or
2440
- n = any ( PostUpdateNode n1 | primaryConstructorParameterStore ( _, c , n1 ) ) .getPreUpdateNode ( )
2441
- or
2442
- VariableCapture:: clearsContent ( n , c )
2443
2480
}
2444
2481
2445
2482
/**
@@ -2449,7 +2486,7 @@ predicate clearsContent(Node n, ContentSet c) {
2449
2486
predicate expectsContent ( Node n , ContentSet c ) {
2450
2487
FlowSummaryImpl:: Private:: Steps:: summaryExpectsContent ( n .( FlowSummaryNode ) .getSummaryNode ( ) , c )
2451
2488
or
2452
- n .asExpr ( ) instanceof SpreadElementExpr and c instanceof ElementContent
2489
+ n .asExpr ( ) instanceof SpreadElementExpr and c . isElement ( )
2453
2490
}
2454
2491
2455
2492
class NodeRegion instanceof ControlFlow:: BasicBlock {
@@ -3050,8 +3087,3 @@ abstract class SyntheticField extends string {
3050
3087
/** Gets the type of this synthetic field. */
3051
3088
Type getType ( ) { result instanceof ObjectType }
3052
3089
}
3053
-
3054
- /**
3055
- * Holds if the the content `c` is a container.
3056
- */
3057
- predicate containerContent ( DataFlow:: Content c ) { c instanceof DataFlow:: ElementContent }
0 commit comments