@@ -45,6 +45,8 @@ private module Cached {
45
45
CopyStep ( PropertyName prop ) or
46
46
LoadStoreStep ( PropertyName fromProp , PropertyName toProp ) {
47
47
SharedTypeTrackingStep:: loadStoreStep ( _, _, fromProp , toProp )
48
+ or
49
+ summarizedLoadStoreStep ( _, _, fromProp , toProp )
48
50
} or
49
51
WithoutPropStep ( PropertySet props ) { SharedTypeTrackingStep:: withoutPropStep ( _, _, props ) }
50
52
}
@@ -69,6 +71,26 @@ private module Cached {
69
71
AccessPath:: isAssignedInUniqueFile ( global )
70
72
}
71
73
74
+ bindingset [ fun]
75
+ pragma [ inline_late]
76
+ private DataFlow:: PropRead getStoredPropRead ( DataFlow:: FunctionNode fun , string storeProp ) {
77
+ result = fun .getAReturn ( ) .getALocalSource ( ) .getAPropertySource ( storeProp )
78
+ }
79
+
80
+ /**
81
+ * Holds if `loadProp` of `param` is stored in the `storeProp` property of the return value of `fun`.
82
+ */
83
+ pragma [ nomagic]
84
+ private predicate summarizedLoadStoreStep (
85
+ DataFlow:: ParameterNode param , DataFlow:: FunctionNode fun , string loadProp , string storeProp
86
+ ) {
87
+ exists ( DataFlow:: PropRead read |
88
+ read = getStoredPropRead ( fun , storeProp ) and
89
+ read .getBase ( ) .getALocalSource ( ) = param and
90
+ read .getPropertyName ( ) = loadProp
91
+ )
92
+ }
93
+
72
94
/**
73
95
* INTERNAL: Use `TypeBackTracker.smallstep()` instead.
74
96
*/
@@ -156,6 +178,14 @@ private module Cached {
156
178
exists ( string prop |
157
179
param .getAPropertyRead ( prop ) .flowsTo ( fun .getAReturn ( ) ) and
158
180
summary = LoadStep ( prop )
181
+ or
182
+ fun .getAReturn ( ) .getALocalSource ( ) .getAPropertySource ( prop ) = param and
183
+ summary = StoreStep ( prop )
184
+ )
185
+ or
186
+ exists ( string loadProp , string storeProp |
187
+ summarizedLoadStoreStep ( param , fun , loadProp , storeProp ) and
188
+ summary = LoadStoreStep ( loadProp , storeProp )
159
189
)
160
190
) and
161
191
if param = fun .getAParameter ( )
0 commit comments