@@ -908,19 +908,20 @@ private class Argument extends Expr {
908908 *
909909 * `postUpdate` indicates whether the store targets a post-update node.
910910 */
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 ) {
912912 exists ( FieldOrProperty f |
913- c = f .getContent ( ) and
913+ c = f .getContentSet ( ) and
914914 (
915915 f .isFieldLike ( ) and
916916 f instanceof InstanceFieldOrProperty
917917 or
918918 exists (
919919 FlowSummaryImpl:: Private:: SummarizedCallableImpl sc ,
920- FlowSummaryImpl:: Private:: SummaryComponentStack input
920+ FlowSummaryImpl:: Private:: SummaryComponentStack input , ContentSet readSet
921921 |
922922 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 ( )
924925 )
925926 )
926927 |
@@ -970,28 +971,13 @@ private predicate fieldOrPropertyStore(Expr e, Content c, Expr src, Expr q, bool
970971 )
971972}
972973
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-
980974/**
981975 * 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`.
984977 */
985- private predicate fieldOrPropertyRead ( Expr e1 , Content c , FieldOrPropertyRead e2 ) {
978+ private predicate fieldOrPropertyRead ( Expr e1 , ContentSet c , FieldOrPropertyRead e2 ) {
986979 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 ( )
995981}
996982
997983/**
@@ -1208,6 +1194,11 @@ private module Cached {
12081194 } or
12091195 TCapturedVariableContent ( VariableCapture:: CapturedVariable v )
12101196
1197+ cached
1198+ newtype TContentSet =
1199+ TSingletonContent ( Content c ) { not c instanceof PropertyContent } or
1200+ TPropertyContentSet ( Property p ) { p .isUnboundDeclaration ( ) }
1201+
12111202 cached
12121203 newtype TContentApprox =
12131204 TFieldApproxContent ( string firstChar ) { firstChar = approximateFieldContent ( _) } or
@@ -2076,10 +2067,10 @@ class FieldOrProperty extends Assignable, Modifiable {
20762067 }
20772068
20782069 /** 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 ( ) )
20812072 or
2082- result .( PropertyContent ) . getProperty ( ) = this .getUnboundDeclaration ( )
2073+ result .isProperty ( this .getUnboundDeclaration ( ) )
20832074 }
20842075}
20852076
@@ -2209,8 +2200,8 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
22092200}
22102201
22112202pragma [ nomagic]
2212- private PropertyContent getResultContent ( ) {
2213- result .getProperty ( ) = any ( SystemThreadingTasksTaskTClass c_ ) .getResultProperty ( )
2203+ private ContentSet getResultContent ( ) {
2204+ result .isProperty ( any ( SystemThreadingTasksTaskTClass c_ ) .getResultProperty ( ) )
22142205}
22152206
22162207private predicate primaryConstructorParameterStore (
@@ -2224,17 +2215,16 @@ private predicate primaryConstructorParameterStore(
22242215 )
22252216}
22262217
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 ) {
22322224 exists ( StoreStepConfiguration x , ExprNode node , boolean postUpdate |
22332225 hasNodePath ( x , node1 , node ) and
22342226 if postUpdate = true then node = node2 .( PostUpdateNode ) .getPreUpdateNode ( ) else node = node2
22352227 |
2236- fieldOrPropertyStore ( _, c , node1 .asExpr ( ) , node .getExpr ( ) , postUpdate )
2237- or
22382228 arrayStore ( _, node1 .asExpr ( ) , node .getExpr ( ) , postUpdate ) and c instanceof ElementContent
22392229 )
22402230 or
@@ -2255,26 +2245,59 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
22552245 c instanceof ElementContent
22562246 )
22572247 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
22582286 exists ( Expr e |
22592287 e = node1 .asExpr ( ) and
22602288 node2 .( AsyncReturnNode ) .getExpr ( ) = e and
22612289 c = getResultContent ( )
22622290 )
22632291 or
2264- primaryConstructorParameterStore ( node1 , c , node2 )
2265- or
2266- exists ( Parameter p , DataFlowCallable callable |
2292+ exists ( Parameter p , DataFlowCallable callable , RecordType t , string name |
22672293 node1 = TExplicitParameterNode ( p , callable ) and
22682294 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 )
22722297 )
22732298 or
22742299 FlowSummaryImpl:: Private:: Steps:: summaryStoreStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
22752300 node2 .( FlowSummaryNode ) .getSummaryNode ( ) )
2276- or
2277- VariableCapture:: storeStep ( node1 , c , node2 )
22782301}
22792302
22802303private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -2342,14 +2365,8 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
23422365 }
23432366}
23442367
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 ) {
23492369 exists ( ReadStepConfiguration x |
2350- hasNodePath ( x , node1 , node2 ) and
2351- fieldOrPropertyRead ( node1 .asExpr ( ) , c , node2 .asExpr ( ) )
2352- or
23532370 hasNodePath ( x , node1 , node2 ) and
23542371 arrayRead ( node1 .asExpr ( ) , node2 .asExpr ( ) ) and
23552372 c instanceof ElementContent
@@ -2361,10 +2378,6 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
23612378 c instanceof ElementContent
23622379 )
23632380 or
2364- hasNodePath ( x , node1 , node2 ) and
2365- node2 .asExpr ( ) .( AwaitExpr ) .getExpr ( ) = node1 .asExpr ( ) and
2366- c = getResultContent ( )
2367- or
23682381 node1 =
23692382 any ( InstanceParameterAccessPreNode n |
23702383 n .getUnderlyingControlFlowNode ( ) = node2 .( ExprNode ) .getControlFlowNode ( ) and
@@ -2402,10 +2415,41 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
24022415 )
24032416 )
24042417 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
24052437 FlowSummaryImpl:: Private:: Steps:: summaryReadStep ( node1 .( FlowSummaryNode ) .getSummaryNode ( ) , c ,
24062438 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+ )
24072449 or
2408- VariableCapture:: readStep ( node1 , c , node2 )
2450+ n = any ( PostUpdateNode n1 | primaryConstructorParameterStore ( _, c , n1 ) ) .getPreUpdateNode ( )
2451+ or
2452+ VariableCapture:: clearsContent ( n , c )
24092453}
24102454
24112455/**
@@ -2414,6 +2458,11 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
24142458 * in `x.f = newValue`.
24152459 */
24162460predicate clearsContent ( Node n , ContentSet c ) {
2461+ exists ( Content cont |
2462+ clearsCont ( n , cont ) and
2463+ c .isSingleton ( cont )
2464+ )
2465+ or
24172466 fieldOrPropertyStore ( _, c , _, n .asExpr ( ) , true )
24182467 or
24192468 fieldOrPropertyStore ( _, c , _, n .( ObjectInitializerNode ) .getInitializer ( ) , false )
@@ -2424,20 +2473,8 @@ predicate clearsContent(Node n, ContentSet c) {
24242473 oi = we .getInitializer ( ) and
24252474 n .asExpr ( ) = oi and
24262475 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 ( )
24362477 )
2437- or
2438- n = any ( PostUpdateNode n1 | primaryConstructorParameterStore ( _, c , n1 ) ) .getPreUpdateNode ( )
2439- or
2440- VariableCapture:: clearsContent ( n , c )
24412478}
24422479
24432480/**
@@ -2447,7 +2484,7 @@ predicate clearsContent(Node n, ContentSet c) {
24472484predicate expectsContent ( Node n , ContentSet c ) {
24482485 FlowSummaryImpl:: Private:: Steps:: summaryExpectsContent ( n .( FlowSummaryNode ) .getSummaryNode ( ) , c )
24492486 or
2450- n .asExpr ( ) instanceof SpreadElementExpr and c instanceof ElementContent
2487+ n .asExpr ( ) instanceof SpreadElementExpr and c . isElement ( )
24512488}
24522489
24532490class NodeRegion instanceof ControlFlow:: BasicBlock {
@@ -3048,8 +3085,3 @@ abstract class SyntheticField extends string {
30483085 /** Gets the type of this synthetic field. */
30493086 Type getType ( ) { result instanceof ObjectType }
30503087}
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