11/**
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.
55 */
66
77import javascript
88private import semmle.javascript.dataflow.internal.StepSummary
99private import DataFlow:: PseudoProperties
1010
1111/**
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.)
1317 */
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 ( ) }
3020
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+ }
3526
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 ( ) }
3931
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+ }
4435
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 ( ) }
4840
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+ }
5344
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 ( ) }
5749
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+ }
6453
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+ }
7060
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 )
7565 }
66+
67+ /**
68+ * Holds if this step on a collection can load a value with a known key.
69+ */
70+ predicate canLoadValueWithKnownKey ( ) { none ( ) }
7671}
7772
7873/**
79- * A collection of predicates and clases for type-tracking Maps and Sets .
74+ * A collection of predicates and clases for type-tracking collections .
8075 */
81- module MapsAndSetsTypeTracking {
82- private import MapsAndSets
83-
76+ module CollectionsTypeTracking {
8477 /**
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`.
8679 */
8780 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 |
9083 summary = LoadStep ( field ) and
9184 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.
9386 or
9487 summary = StoreStep ( field ) and
9588 step .store ( pred , result , field )
@@ -104,42 +97,40 @@ module MapsAndSetsTypeTracking {
10497 }
10598
10699 /**
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`.
108101 */
109102 pragma [ inline]
110- DataFlow:: SourceNode mapOrSetStep (
103+ DataFlow:: SourceNode collectionStep (
111104 DataFlow:: SourceNode pred , DataFlow:: TypeTracker t , DataFlow:: TypeTracker t2
112105 ) {
113106 exists ( DataFlow:: Node mid , StepSummary summary | pred .flowsTo ( mid ) and t = t2 .append ( summary ) |
114- result = mapOrSetStep ( mid , summary )
107+ result = collectionStep ( mid , summary )
115108 )
116109 }
117110
118111 /**
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.
120113 */
121114 private class MapRelatedPseudoFieldAsTypeTrackingProperty extends TypeTrackingPseudoProperty {
122115 MapRelatedPseudoFieldAsTypeTrackingProperty ( ) {
123116 this = [ setElement ( ) , iteratorElement ( ) ] or
124- any ( MapOrSetFlowStep step ) .store ( _, _, this )
117+ any ( CollectionFlowStep step ) .store ( _, _, this )
125118 }
126119
127120 override string getLoadStoreToProp ( ) {
128- exists ( MapOrSetFlowStep step | step .loadStore ( _, _, this , result ) )
121+ exists ( CollectionFlowStep step | step .loadStore ( _, _, this , result ) )
129122 }
130123 }
131124}
132125
133126/**
134- * A module for data-flow steps related to `Set` and `Map` .
127+ * A module for data-flow steps related standard library collection implementations .
135128 */
136- private module MapAndSetDataFlow {
137- private import MapsAndSets
138-
129+ private module CollectionDataFlow {
139130 /**
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.
141132 */
142- private class SetAdd extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
133+ private class SetAdd extends CollectionFlowStep , DataFlow:: MethodCallNode {
143134 SetAdd ( ) { this .getMethodName ( ) = "add" }
144135
145136 override predicate store ( DataFlow:: Node element , DataFlow:: Node obj , string prop ) {
@@ -152,7 +143,7 @@ private module MapAndSetDataFlow {
152143 /**
153144 * A step for the `Set` constructor, which copies any elements from the first argument into the resulting set.
154145 */
155- private class SetConstructor extends MapOrSetFlowStep , DataFlow:: NewNode {
146+ private class SetConstructor extends CollectionFlowStep , DataFlow:: NewNode {
156147 SetConstructor ( ) { this = DataFlow:: globalVarRef ( "Set" ) .getAnInstantiation ( ) }
157148
158149 override predicate loadStore (
@@ -171,9 +162,9 @@ private module MapAndSetDataFlow {
171162 * For Maps the l-value is a tuple containing a key and a value.
172163 *
173164 * 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 `.
175166 */
176- private class ForOfStep extends MapOrSetFlowStep , DataFlow:: ValueNode {
167+ private class ForOfStep extends CollectionFlowStep , DataFlow:: ValueNode {
177168 ForOfStmt forOf ;
178169 DataFlow:: Node element ;
179170
@@ -201,7 +192,7 @@ private module MapAndSetDataFlow {
201192 /**
202193 * A step for a call to `forEach` on a Set or Map.
203194 */
204- private class SetMapForEach extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
195+ private class SetMapForEach extends CollectionFlowStep , DataFlow:: MethodCallNode {
205196 SetMapForEach ( ) { this .getMethodName ( ) = "forEach" }
206197
207198 override predicate load ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
@@ -215,7 +206,7 @@ private module MapAndSetDataFlow {
215206 * A call to the `get` method on a Map.
216207 * If the key of the call to `get` has a known string value, then only the value corresponding to that key will be retrieved.
217208 */
218- private class MapGet extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
209+ private class MapGet extends CollectionFlowStep , DataFlow:: MethodCallNode {
219210 MapGet ( ) { this .getMethodName ( ) = "get" }
220211
221212 override predicate load ( DataFlow:: Node obj , DataFlow:: Node element , string prop ) {
@@ -224,7 +215,7 @@ private module MapAndSetDataFlow {
224215 prop = mapValue ( this .getArgument ( 0 ) )
225216 }
226217
227- override predicate canLoadKnownKey ( ) { any ( ) }
218+ override predicate canLoadValueWithKnownKey ( ) { any ( ) }
228219 }
229220
230221 /**
@@ -234,7 +225,7 @@ private module MapAndSetDataFlow {
234225 * then the value will be saved into a pseudo-property corresponding to the known string value.
235226 * The value will additionally be saved into a pseudo-property corresponding to values with unknown keys.
236227 */
237- private class MapSet extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
228+ private class MapSet extends CollectionFlowStep , DataFlow:: MethodCallNode {
238229 MapSet ( ) { this .getMethodName ( ) = "set" }
239230
240231 override predicate store ( DataFlow:: Node element , DataFlow:: Node obj , string prop ) {
@@ -248,7 +239,7 @@ private module MapAndSetDataFlow {
248239 /**
249240 * A step for a call to `values` on a Map or a Set.
250241 */
251- private class MapAndSetValues extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
242+ private class MapAndSetValues extends CollectionFlowStep , DataFlow:: MethodCallNode {
252243 MapAndSetValues ( ) { this .getMethodName ( ) = "values" }
253244
254245 override predicate loadStore (
@@ -264,7 +255,7 @@ private module MapAndSetDataFlow {
264255 /**
265256 * A step for a call to `keys` on a Set.
266257 */
267- private class SetKeys extends MapOrSetFlowStep , DataFlow:: MethodCallNode {
258+ private class SetKeys extends CollectionFlowStep , DataFlow:: MethodCallNode {
268259 SetKeys ( ) { this .getMethodName ( ) = "keys" }
269260
270261 override predicate loadStore (
0 commit comments