@@ -81,11 +81,6 @@ abstract private class CollectionFlowStep extends DataFlow::AdditionalFlowStep {
81
81
) {
82
82
this .loadStore ( pred , succ , loadProp , storeProp )
83
83
}
84
-
85
- /**
86
- * Holds if this step on a collection can load a value with a known key.
87
- */
88
- predicate canLoadValueWithKnownKey ( ) { none ( ) }
89
84
}
90
85
91
86
/**
@@ -100,10 +95,7 @@ module CollectionsTypeTracking {
100
95
exists ( CollectionFlowStep step , PseudoProperty field |
101
96
summary = LoadStep ( field ) and
102
97
step .load ( pred , result , field ) and
103
- not (
104
- step .canLoadValueWithKnownKey ( ) and // for a step that could load a known key,
105
- field = mapValueUnknownKey ( ) // don't load values with an unknown key.
106
- )
98
+ not field = mapValueUnknownKey ( ) // prune unknown reads in type-tracking
107
99
or
108
100
summary = StoreStep ( field ) and
109
101
step .store ( pred , result , field )
@@ -191,7 +183,7 @@ private module CollectionDataFlow {
191
183
) {
192
184
pred = this and
193
185
succ = element and
194
- fromProp = mapValueUnknownKey ( ) and
186
+ fromProp = mapValueAll ( ) and
195
187
toProp = "1"
196
188
}
197
189
}
@@ -205,7 +197,7 @@ private module CollectionDataFlow {
205
197
override predicate load ( DataFlow:: Node obj , DataFlow:: Node element , PseudoProperty prop ) {
206
198
obj = this .getReceiver ( ) and
207
199
element = this .getCallback ( 0 ) .getParameter ( 0 ) and
208
- prop = [ setElement ( ) , mapValueUnknownKey ( ) ]
200
+ prop = [ setElement ( ) , mapValueAll ( ) ]
209
201
}
210
202
}
211
203
@@ -219,18 +211,18 @@ private module CollectionDataFlow {
219
211
override predicate load ( DataFlow:: Node obj , DataFlow:: Node element , PseudoProperty prop ) {
220
212
obj = this .getReceiver ( ) and
221
213
element = this and
222
- prop = mapValue ( this .getArgument ( 0 ) )
214
+ // reading the join of known and unknown values
215
+ ( prop = mapValue ( this .getArgument ( 0 ) ) or prop = mapValueUnknownKey ( ) )
223
216
}
224
-
225
- override predicate canLoadValueWithKnownKey ( ) { any ( ) }
226
217
}
227
218
228
219
/**
229
220
* A call to the `set` method on a Map.
230
221
*
231
222
* If the key of the call to `set` has a known string value,
232
223
* then the value will be saved into a pseudo-property corresponding to the known string value.
233
- * The value will additionally be saved into a pseudo-property corresponding to values with unknown keys.
224
+ * Otherwise the value will be saved into a pseudo-property corresponding to values with unknown keys.
225
+ * The value will additionally be saved into a pseudo-property corresponding to all values.
234
226
*/
235
227
class MapSet extends CollectionFlowStep , DataFlow:: MethodCallNode {
236
228
MapSet ( ) { this .getMethodName ( ) = "set" }
@@ -246,9 +238,11 @@ private module CollectionDataFlow {
246
238
* The pseudo-property represents both values where the key is a known string value (which is encoded in the pseudo-property),
247
239
* and values where the key is unknown.
248
240
*
241
+ * Additionally, all elements are stored into the pseudo-property `mapValueAll()`.
242
+ *
249
243
* The return-type is `string` as this predicate is used to define which pseudo-properties exist.
250
244
*/
251
- string getAPseudoProperty ( ) { result = [ mapValue ( this .getArgument ( 0 ) ) , mapValueUnknownKey ( ) ] }
245
+ string getAPseudoProperty ( ) { result = [ mapValue ( this .getArgument ( 0 ) ) , mapValueAll ( ) ] }
252
246
}
253
247
254
248
/**
@@ -262,7 +256,7 @@ private module CollectionDataFlow {
262
256
) {
263
257
pred = this .getReceiver ( ) and
264
258
succ = this and
265
- fromProp = [ mapValueUnknownKey ( ) , setElement ( ) ] and
259
+ fromProp = [ mapValueAll ( ) , setElement ( ) ] and
266
260
toProp = iteratorElement ( )
267
261
}
268
262
}
0 commit comments