1
1
/**
2
- * Provides predicates and classes for working with the standard library implementations of
3
- * [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and
4
- * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
2
+ * Provides predicates and classes for working with the standard library collection implementations.
3
+ * Currently [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and
4
+ * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) are implemented.
5
5
*/
6
6
7
7
import javascript
8
8
private import semmle.javascript.dataflow.internal.StepSummary
9
9
private import DataFlow:: PseudoProperties
10
10
11
11
/**
12
- * Common predicates and classes for type and data-flow tracking on Maps and Sets.
12
+ * An `AdditionalFlowStep` used to model a data-flow step related to standard library collections.
13
+ *
14
+ * The `loadStep`/`storeStep`/`loadStoreStep` methods are overloaded such that the new predicates
15
+ * `load`/`store`/`loadStore` can be used in the `CollectionsTypeTracking` module.
16
+ * (Thereby avoiding naming conflicts with a "cousin" `AdditionalFlowStep` implementation.)
13
17
*/
14
- private module MapsAndSets {
15
- /**
16
- * An `AdditionalFlowStep` used to model a data-flow step related to Maps and Sets.
17
- *
18
- * The `loadStep`/`storeStep`/`loadStoreStep` methods are overloaded such that the new predicates
19
- * `load`/`store`/`loadStore` can be used in the `MapsAndSetsTypeTracking` module.
20
- * (Thereby avoiding conflicts with a "cousin" `AdditionalFlowStep` implementation.)
21
- */
22
- abstract class MapOrSetFlowStep extends DataFlow:: AdditionalFlowStep {
23
- final override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) { none ( ) }
24
-
25
- final override predicate step (
26
- DataFlow:: Node p , DataFlow:: Node s , DataFlow:: FlowLabel pl , DataFlow:: FlowLabel sl
27
- ) {
28
- none ( )
29
- }
18
+ private abstract class CollectionFlowStep extends DataFlow:: AdditionalFlowStep {
19
+ final override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) { none ( ) }
30
20
31
- /**
32
- * Holds if the property `prop` of the object `pred` should be loaded into `succ`.
33
- */
34
- predicate load ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) { none ( ) }
21
+ final override predicate step (
22
+ DataFlow:: Node p , DataFlow:: Node s , DataFlow:: FlowLabel pl , DataFlow:: FlowLabel sl
23
+ ) {
24
+ none ( )
25
+ }
35
26
36
- final override predicate loadStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
37
- this .load ( pred , succ , prop )
38
- }
27
+ /**
28
+ * Holds if the property `prop` of the object `pred` should be loaded into `succ`.
29
+ */
30
+ predicate load ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) { none ( ) }
39
31
40
- /**
41
- * Holds if `pred` should be stored in the object `succ` under the property `prop`.
42
- */
43
- predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) { none ( ) }
32
+ final override predicate loadStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
33
+ this .load ( pred , succ , prop )
34
+ }
44
35
45
- final override predicate storeStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
46
- this .store ( pred , succ , prop )
47
- }
36
+ /**
37
+ * Holds if `pred` should be stored in the object `succ` under the property `prop`.
38
+ */
39
+ predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) { none ( ) }
48
40
49
- /**
50
- * Holds if the property `prop` should be copied from the object `pred` to the object `succ`.
51
- */
52
- predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) { none ( ) }
41
+ final override predicate storeStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
42
+ this .store ( pred , succ , prop )
43
+ }
53
44
54
- final override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
55
- this .loadStore ( pred , succ , prop , prop )
56
- }
45
+ /**
46
+ * Holds if the property `prop` should be copied from the object `pred` to the object `succ`.
47
+ */
48
+ predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) { none ( ) }
57
49
58
- /**
59
- * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`.
60
- */
61
- predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string loadProp , string storeProp ) {
62
- none ( )
63
- }
50
+ final override predicate loadStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
51
+ this .loadStore ( pred , succ , prop , prop )
52
+ }
64
53
65
- final override predicate loadStoreStep (
66
- DataFlow:: Node pred , DataFlow:: Node succ , string loadProp , string storeProp
67
- ) {
68
- this .loadStore ( pred , succ , loadProp , storeProp )
69
- }
54
+ /**
55
+ * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`.
56
+ */
57
+ predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string loadProp , string storeProp ) {
58
+ none ( )
59
+ }
70
60
71
- /**
72
- * Holds if this is a map step that could potentially load a value where the corresponding key has a known string value.
73
- */
74
- predicate canLoadKnownKey ( ) { none ( ) }
61
+ final override predicate loadStoreStep (
62
+ DataFlow :: Node pred , DataFlow :: Node succ , string loadProp , string storeProp
63
+ ) {
64
+ this . loadStore ( pred , succ , loadProp , storeProp )
75
65
}
66
+
67
+ /**
68
+ * Holds if this step on a collection can load a value with a known key.
69
+ */
70
+ predicate canLoadValueWithKnownKey ( ) { none ( ) }
76
71
}
77
72
78
73
/**
79
- * A collection of predicates and clases for type-tracking Maps and Sets .
74
+ * A collection of predicates and clases for type-tracking collections .
80
75
*/
81
- module MapsAndSetsTypeTracking {
82
- private import MapsAndSets
83
-
76
+ module CollectionsTypeTracking {
84
77
/**
85
- * Gets the result from a single step through a Map or Set , from `pred` to `result` summarized by `summary`.
78
+ * Gets the result from a single step through a collection , from `pred` to `result` summarized by `summary`.
86
79
*/
87
80
pragma [ inline]
88
- DataFlow:: SourceNode mapOrSetStep ( DataFlow:: Node pred , StepSummary summary ) {
89
- exists ( MapOrSetFlowStep step , string field |
81
+ DataFlow:: SourceNode collectionStep ( DataFlow:: Node pred , StepSummary summary ) {
82
+ exists ( CollectionFlowStep step , string field |
90
83
summary = LoadStep ( field ) and
91
84
step .load ( pred , result , field ) and
92
- ( not step .canLoadKnownKey ( ) or not field = mapValueUnknownKey ( ) ) // for a step that could load a known key, we prune the steps where the key is unknown.
85
+ ( not step .canLoadValueWithKnownKey ( ) or not field = mapValueUnknownKey ( ) ) // for a step that could load a known key, we prune the steps where the key is unknown.
93
86
or
94
87
summary = StoreStep ( field ) and
95
88
step .store ( pred , result , field )
@@ -104,42 +97,40 @@ module MapsAndSetsTypeTracking {
104
97
}
105
98
106
99
/**
107
- * Gets the result from a single step through a Map or set , from `pred` with tracker `t2` to `result` with tracker `t`.
100
+ * Gets the result from a single step through a collection , from `pred` with tracker `t2` to `result` with tracker `t`.
108
101
*/
109
102
pragma [ inline]
110
- DataFlow:: SourceNode mapOrSetStep (
103
+ DataFlow:: SourceNode collectionStep (
111
104
DataFlow:: SourceNode pred , DataFlow:: TypeTracker t , DataFlow:: TypeTracker t2
112
105
) {
113
106
exists ( DataFlow:: Node mid , StepSummary summary | pred .flowsTo ( mid ) and t = t2 .append ( summary ) |
114
- result = mapOrSetStep ( mid , summary )
107
+ result = collectionStep ( mid , summary )
115
108
)
116
109
}
117
110
118
111
/**
119
- * A class enabling the use of the Map and Set related pseudo-properties as a pseudo-property in type-tracking predicates.
112
+ * A class enabling the use of the collection related pseudo-properties in type-tracking predicates.
120
113
*/
121
114
private class MapRelatedPseudoFieldAsTypeTrackingProperty extends TypeTrackingPseudoProperty {
122
115
MapRelatedPseudoFieldAsTypeTrackingProperty ( ) {
123
116
this = [ setElement ( ) , iteratorElement ( ) ] or
124
- any ( MapOrSetFlowStep step ) .store ( _, _, this )
117
+ any ( CollectionFlowStep step ) .store ( _, _, this )
125
118
}
126
119
127
120
override string getLoadStoreToProp ( ) {
128
- exists ( MapOrSetFlowStep step | step .loadStore ( _, _, this , result ) )
121
+ exists ( CollectionFlowStep step | step .loadStore ( _, _, this , result ) )
129
122
}
130
123
}
131
124
}
132
125
133
126
/**
134
- * A module for data-flow steps related to `Set` and `Map` .
127
+ * A module for data-flow steps related standard library collection implementations .
135
128
*/
136
- private module MapAndSetDataFlow {
137
- private import MapsAndSets
138
-
129
+ private module CollectionDataFlow {
139
130
/**
140
- * A step for an ` add` method, which adds an element to a Set.
131
+ * A step for `Set. add() ` method, which adds an element to a Set.
141
132
*/
142
- private class SetAdd extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
133
+ private class SetAdd extends CollectionFlowStep , DataFlow:: MethodCallNode {
143
134
SetAdd ( ) { this .getMethodName ( ) = "add" }
144
135
145
136
override predicate store ( DataFlow:: Node element , DataFlow:: Node obj , string prop ) {
@@ -152,7 +143,7 @@ private module MapAndSetDataFlow {
152
143
/**
153
144
* A step for the `Set` constructor, which copies any elements from the first argument into the resulting set.
154
145
*/
155
- private class SetConstructor extends MapOrSetFlowStep , DataFlow:: NewNode {
146
+ private class SetConstructor extends CollectionFlowStep , DataFlow:: NewNode {
156
147
SetConstructor ( ) { this = DataFlow:: globalVarRef ( "Set" ) .getAnInstantiation ( ) }
157
148
158
149
override predicate loadStore (
@@ -171,9 +162,9 @@ private module MapAndSetDataFlow {
171
162
* For Maps the l-value is a tuple containing a key and a value.
172
163
*
173
164
* This is partially duplicated behavior with the `for of` step for Arrays (in Arrays.qll).
174
- * This duplication is required for the type-tracking steps defined in `MapsAndSetsTypeTracking `.
165
+ * This duplication is required for the type-tracking steps defined in `CollectionsTypeTracking `.
175
166
*/
176
- private class ForOfStep extends MapOrSetFlowStep , DataFlow:: ValueNode {
167
+ private class ForOfStep extends CollectionFlowStep , DataFlow:: ValueNode {
177
168
ForOfStmt forOf ;
178
169
DataFlow:: Node element ;
179
170
@@ -201,7 +192,7 @@ private module MapAndSetDataFlow {
201
192
/**
202
193
* A step for a call to `forEach` on a Set or Map.
203
194
*/
204
- private class SetMapForEach extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
195
+ private class SetMapForEach extends CollectionFlowStep , DataFlow:: MethodCallNode {
205
196
SetMapForEach ( ) { this .getMethodName ( ) = "forEach" }
206
197
207
198
override predicate load ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
@@ -215,7 +206,7 @@ private module MapAndSetDataFlow {
215
206
* A call to the `get` method on a Map.
216
207
* If the key of the call to `get` has a known string value, then only the value corresponding to that key will be retrieved.
217
208
*/
218
- private class MapGet extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
209
+ private class MapGet extends CollectionFlowStep , DataFlow:: MethodCallNode {
219
210
MapGet ( ) { this .getMethodName ( ) = "get" }
220
211
221
212
override predicate load ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
@@ -224,7 +215,7 @@ private module MapAndSetDataFlow {
224
215
prop = mapValue ( this .getArgument ( 0 ) )
225
216
}
226
217
227
- override predicate canLoadKnownKey ( ) { any ( ) }
218
+ override predicate canLoadValueWithKnownKey ( ) { any ( ) }
228
219
}
229
220
230
221
/**
@@ -234,7 +225,7 @@ private module MapAndSetDataFlow {
234
225
* then the value will be saved into a pseudo-property corresponding to the known string value.
235
226
* The value will additionally be saved into a pseudo-property corresponding to values with unknown keys.
236
227
*/
237
- private class MapSet extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
228
+ private class MapSet extends CollectionFlowStep , DataFlow:: MethodCallNode {
238
229
MapSet ( ) { this .getMethodName ( ) = "set" }
239
230
240
231
override predicate store ( DataFlow:: Node element , DataFlow:: Node obj , string prop ) {
@@ -248,7 +239,7 @@ private module MapAndSetDataFlow {
248
239
/**
249
240
* A step for a call to `values` on a Map or a Set.
250
241
*/
251
- private class MapAndSetValues extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
242
+ private class MapAndSetValues extends CollectionFlowStep , DataFlow:: MethodCallNode {
252
243
MapAndSetValues ( ) { this .getMethodName ( ) = "values" }
253
244
254
245
override predicate loadStore (
@@ -264,7 +255,7 @@ private module MapAndSetDataFlow {
264
255
/**
265
256
* A step for a call to `keys` on a Set.
266
257
*/
267
- private class SetKeys extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
258
+ private class SetKeys extends CollectionFlowStep , DataFlow:: MethodCallNode {
268
259
SetKeys ( ) { this .getMethodName ( ) = "keys" }
269
260
270
261
override predicate loadStore (
0 commit comments