@@ -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
@@ -2209,8 +2200,8 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
2209
2200
}
2210
2201
2211
2202
pragma [ nomagic]
2212
- private PropertyContent getResultContent ( ) {
2213
- result .getProperty ( ) = any ( SystemThreadingTasksTaskTClass c_ ) .getResultProperty ( )
2203
+ private ContentSet getResultContent ( ) {
2204
+ result .isProperty ( any ( SystemThreadingTasksTaskTClass c_ ) .getResultProperty ( ) )
2214
2205
}
2215
2206
2216
2207
private predicate primaryConstructorParameterStore (
@@ -2224,17 +2215,16 @@ private predicate primaryConstructorParameterStore(
2224
2215
)
2225
2216
}
2226
2217
2227
- /**
2228
- * Holds if data can flow from `node1` to `node2` via an assignment to
2229
- * content `c`.
2230
- */
2231
- predicate storeStep ( Node node1 , ContentSet c , Node node2 ) {
2218
+ pragma [ nomagic]
2219
+ private predicate recordParameter ( RecordType t , Parameter p , string name ) {
2220
+ p .getName ( ) = name and p .getCallable ( ) .getDeclaringType ( ) = t
2221
+ }
2222
+
2223
+ private predicate storeContentStep ( Node node1 , Content c , Node node2 ) {
2232
2224
exists ( StoreStepConfiguration x , ExprNode node , boolean postUpdate |
2233
2225
hasNodePath ( x , node1 , node ) and
2234
2226
if postUpdate = true then node = node2 .( PostUpdateNode ) .getPreUpdateNode ( ) else node = node2
2235
2227
|
2236
- fieldOrPropertyStore ( _, c , node1 .asExpr ( ) , node .getExpr ( ) , postUpdate )
2237
- or
2238
2228
arrayStore ( _, node1 .asExpr ( ) , node .getExpr ( ) , postUpdate ) and c instanceof ElementContent
2239
2229
)
2240
2230
or
@@ -2255,26 +2245,59 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
2255
2245
c instanceof ElementContent
2256
2246
)
2257
2247
or
2248
+ primaryConstructorParameterStore ( node1 , c , node2 )
2249
+ or
2250
+ exists ( Parameter p , DataFlowCallable callable |
2251
+ node1 = TExplicitParameterNode ( p , callable ) and
2252
+ node2 = TPrimaryConstructorThisAccessNode ( p , true , callable ) and
2253
+ not recordParameter ( _, p , _) and
2254
+ c .( PrimaryConstructorParameterContent ) .getParameter ( ) = p
2255
+ )
2256
+ or
2257
+ VariableCapture:: storeStep ( node1 , c , node2 )
2258
+ }
2259
+
2260
+ pragma [ nomagic]
2261
+ private predicate recordProperty ( RecordType t , ContentSet c , string name ) {
2262
+ exists ( Property p |
2263
+ c .isProperty ( p ) and
2264
+ p .getName ( ) = name and
2265
+ p .getDeclaringType ( ) = t
2266
+ )
2267
+ }
2268
+
2269
+ /**
2270
+ * Holds if data can flow from `node1` to `node2` via an assignment to
2271
+ * content `c`.
2272
+ */
2273
+ predicate storeStep ( Node node1 , ContentSet c , Node node2 ) {
2274
+ exists ( Content cont |
2275
+ storeContentStep ( node1 , cont , node2 ) and
2276
+ c .isSingleton ( cont )
2277
+ )
2278
+ or
2279
+ exists ( StoreStepConfiguration x , ExprNode node , boolean postUpdate |
2280
+ hasNodePath ( x , node1 , node ) and
2281
+ if postUpdate = true then node = node2 .( PostUpdateNode ) .getPreUpdateNode ( ) else node = node2
2282
+ |
2283
+ fieldOrPropertyStore ( _, c , node1 .asExpr ( ) , node .getExpr ( ) , postUpdate )
2284
+ )
2285
+ or
2258
2286
exists ( Expr e |
2259
2287
e = node1 .asExpr ( ) and
2260
2288
node2 .( AsyncReturnNode ) .getExpr ( ) = e and
2261
2289
c = getResultContent ( )
2262
2290
)
2263
2291
or
2264
- primaryConstructorParameterStore ( node1 , c , node2 )
2265
- or
2266
- exists ( Parameter p , DataFlowCallable callable |
2292
+ exists ( Parameter p , DataFlowCallable callable , RecordType t , string name |
2267
2293
node1 = TExplicitParameterNode ( p , callable ) and
2268
2294
node2 = TPrimaryConstructorThisAccessNode ( p , true , callable ) and
2269
- if p .getCallable ( ) .getDeclaringType ( ) instanceof RecordType
2270
- then c .( PropertyContent ) .getProperty ( ) .getName ( ) = p .getName ( )
2271
- else c .( PrimaryConstructorParameterContent ) .getParameter ( ) = p
2295
+ recordParameter ( t , p , name ) and
2296
+ recordProperty ( t , c , name )
2272
2297
)
2273
2298
or
2274
2299
FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
2275
2300
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2276
- or
2277
- VariableCapture:: storeStep ( node1 , c , node2 )
2278
2301
}
2279
2302
2280
2303
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -2342,14 +2365,8 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
2342
2365
}
2343
2366
}
2344
2367
2345
- /**
2346
- * Holds if data can flow from `node1` to `node2` via a read of content `c`.
2347
- */
2348
- predicate readStep ( Node node1 , ContentSet c , Node node2 ) {
2368
+ private predicate readContentStep ( Node node1 , Content c , Node node2 ) {
2349
2369
exists ( ReadStepConfiguration x |
2350
- hasNodePath ( x , node1 , node2 ) and
2351
- fieldOrPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2352
- or
2353
2370
hasNodePath ( x , node1 , node2 ) and
2354
2371
arrayRead ( node1 .asExpr ( ) , node2 .asExpr ( ) ) and
2355
2372
c instanceof ElementContent
@@ -2361,10 +2378,6 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2361
2378
c instanceof ElementContent
2362
2379
)
2363
2380
or
2364
- hasNodePath ( x , node1 , node2 ) and
2365
- node2 .asExpr ( ) .( AwaitExpr ) .getExpr ( ) = node1 .asExpr ( ) and
2366
- c = getResultContent ( )
2367
- or
2368
2381
node1 =
2369
2382
any ( InstanceParameterAccessPreNode n |
2370
2383
n .getUnderlyingControlFlowNode ( ) = node2 .( ExprNode ) .getControlFlowNode ( ) and
@@ -2402,10 +2415,41 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2402
2415
)
2403
2416
)
2404
2417
or
2418
+ VariableCapture:: readStep ( node1 , c , node2 )
2419
+ }
2420
+
2421
+ /**
2422
+ * Holds if data can flow from `node1` to `node2` via a read of content `c`.
2423
+ */
2424
+ predicate readStep ( Node node1 , ContentSet c , Node node2 ) {
2425
+ exists ( Content cont |
2426
+ readContentStep ( node1 , cont , node2 ) and
2427
+ c .isSingleton ( cont )
2428
+ )
2429
+ or
2430
+ exists ( ReadStepConfiguration x | hasNodePath ( x , node1 , node2 ) |
2431
+ fieldOrPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2432
+ or
2433
+ node2 .asExpr ( ) .( AwaitExpr ) .getExpr ( ) = node1 .asExpr ( ) and
2434
+ c = getResultContent ( )
2435
+ )
2436
+ or
2405
2437
FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
2406
2438
node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2439
+ }
2440
+
2441
+ private predicate clearsCont ( Node n , Content c ) {
2442
+ exists ( Argument a , Struct s , Field f |
2443
+ a = n .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) and
2444
+ a .getType ( ) = s and
2445
+ f = s .getAField ( ) and
2446
+ c .( FieldContent ) .getField ( ) = f .getUnboundDeclaration ( ) and
2447
+ not f .isRef ( )
2448
+ )
2407
2449
or
2408
- VariableCapture:: readStep ( node1 , c , node2 )
2450
+ n = any ( PostUpdateNode n1 | primaryConstructorParameterStore ( _, c , n1 ) ) .getPreUpdateNode ( )
2451
+ or
2452
+ VariableCapture:: clearsContent ( n , c )
2409
2453
}
2410
2454
2411
2455
/**
@@ -2414,6 +2458,11 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
2414
2458
* in `x.f = newValue`.
2415
2459
*/
2416
2460
predicate clearsContent ( Node n , ContentSet c ) {
2461
+ exists ( Content cont |
2462
+ clearsCont ( n , cont ) and
2463
+ c .isSingleton ( cont )
2464
+ )
2465
+ or
2417
2466
fieldOrPropertyStore ( _, c , _, n .asExpr ( ) , true )
2418
2467
or
2419
2468
fieldOrPropertyStore ( _, c , _, n .( ObjectInitializerNode ) .getInitializer ( ) , false )
@@ -2424,20 +2473,8 @@ predicate clearsContent(Node n, ContentSet c) {
2424
2473
oi = we .getInitializer ( ) and
2425
2474
n .asExpr ( ) = oi and
2426
2475
f = oi .getAMemberInitializer ( ) .getInitializedMember ( ) and
2427
- c = f .getContent ( )
2428
- )
2429
- or
2430
- exists ( Argument a , Struct s , Field f |
2431
- a = n .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) and
2432
- a .getType ( ) = s and
2433
- f = s .getAField ( ) and
2434
- c .( FieldContent ) .getField ( ) = f .getUnboundDeclaration ( ) and
2435
- not f .isRef ( )
2476
+ c = f .getContentSet ( )
2436
2477
)
2437
- or
2438
- n = any ( PostUpdateNode n1 | primaryConstructorParameterStore ( _, c , n1 ) ) .getPreUpdateNode ( )
2439
- or
2440
- VariableCapture:: clearsContent ( n , c )
2441
2478
}
2442
2479
2443
2480
/**
@@ -2447,7 +2484,7 @@ predicate clearsContent(Node n, ContentSet c) {
2447
2484
predicate expectsContent ( Node n , ContentSet c ) {
2448
2485
FlowSummaryImpl:: Private:: Steps:: summaryExpectsContent ( n .( FlowSummaryNode ) .getSummaryNode ( ) , c )
2449
2486
or
2450
- n .asExpr ( ) instanceof SpreadElementExpr and c instanceof ElementContent
2487
+ n .asExpr ( ) instanceof SpreadElementExpr and c . isElement ( )
2451
2488
}
2452
2489
2453
2490
class NodeRegion instanceof ControlFlow:: BasicBlock {
@@ -3048,8 +3085,3 @@ abstract class SyntheticField extends string {
3048
3085
/** Gets the type of this synthetic field. */
3049
3086
Type getType ( ) { result instanceof ObjectType }
3050
3087
}
3051
-
3052
- /**
3053
- * Holds if the the content `c` is a container.
3054
- */
3055
- predicate containerContent ( DataFlow:: Content c ) { c instanceof DataFlow:: ElementContent }
0 commit comments