@@ -45,6 +45,8 @@ private module Cached {
4545 CopyStep ( PropertyName prop ) or
4646 LoadStoreStep ( PropertyName fromProp , PropertyName toProp ) {
4747 SharedTypeTrackingStep:: loadStoreStep ( _, _, fromProp , toProp )
48+ or
49+ summarizedLoadStoreStep ( _, _, fromProp , toProp )
4850 } or
4951 WithoutPropStep ( PropertySet props ) { SharedTypeTrackingStep:: withoutPropStep ( _, _, props ) }
5052 }
@@ -69,6 +71,26 @@ private module Cached {
6971 AccessPath:: isAssignedInUniqueFile ( global )
7072 }
7173
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+
7294 /**
7395 * INTERNAL: Use `TypeBackTracker.smallstep()` instead.
7496 */
@@ -156,6 +178,14 @@ private module Cached {
156178 exists ( string prop |
157179 param .getAPropertyRead ( prop ) .flowsTo ( fun .getAReturn ( ) ) and
158180 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 )
159189 )
160190 ) and
161191 if param = fun .getAParameter ( )
0 commit comments