Skip to content

Commit 6cbf7b3

Browse files
committed
add of Set, Stack and similar to the Immutable model
1 parent b74df66 commit 6cbf7b3

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

javascript/ql/src/semmle/javascript/frameworks/Immutable.qll

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,18 @@ private module Immutable {
3838
API::Node immutableCollection() {
3939
// keep this predicate in sync with the constructors defined in `storeStep`/`step`.
4040
result =
41-
immutableImport().getMember(["Map", "OrderedMap", "List", "fromJS", "merge"]).getReturn()
41+
immutableImport()
42+
.getMember(["Map", "OrderedMap", "List", "Stack", "Set", "OrderedSet", "fromJS", "merge"])
43+
.getReturn()
4244
or
4345
result = immutableImport().getMember("Record").getReturn().getReturn()
4446
or
47+
result =
48+
immutableImport()
49+
.getMember(["List", "Set", "OrderedSet", "Stack"])
50+
.getMember("of")
51+
.getReturn()
52+
or
4553
result = immutableCollection().getMember(["set", "map", "filter", "push", "merge"]).getReturn()
4654
}
4755

@@ -59,7 +67,7 @@ private module Immutable {
5967
or
6068
// Immutable.List()
6169
exists(DataFlow::CallNode call, DataFlow::ArrayCreationNode arr |
62-
call = immutableImport().getMember("List").getACall()
70+
call = immutableImport().getMember(["List", "Stack", "Set", "OrderedSet"]).getACall()
6371
|
6472
arr = call.getArgument(0).getALocalSource() and
6573
exists(int i |
@@ -91,6 +99,19 @@ private module Immutable {
9199
pred = [factoryCall, recordCall].getOptionArgument(0, prop) and
92100
result = recordCall
93101
)
102+
or
103+
// List/Set/Stack.of(values)
104+
exists(API::CallNode call |
105+
call =
106+
immutableImport()
107+
.getMember(["List", "Set", "OrderedSet", "Stack"])
108+
.getMember("of")
109+
.getACall()
110+
|
111+
pred = call.getAnArgument() and
112+
result = call and
113+
prop = DataFlow::PseudoProperties::arrayElement()
114+
)
94115
}
95116

96117
/**

javascript/ql/test/library-tests/frameworks/Immutable/immutable.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
var obj = { a: source("a"), b: source("b1") };
22
sink(obj["a"]); // NOT OK
33

4-
const { Map, fromJS, List, OrderedMap, Record, merge } = require('immutable');
4+
const { Map, fromJS, List, OrderedMap, Record, merge, Stack, Set, OrderedSet } = require('immutable');
55

66
const map1 = Map(obj);
77

@@ -45,4 +45,14 @@ const map6 = merge(Map({}), Record({a: source()})());
4545
sink(map6.get("a")); // NOT OK
4646

4747
const map7 = map6.merge(Map({b: source()}));
48-
sink(map7.get("b")); // NOT OK
48+
sink(map7.get("b")); // NOT OK
49+
50+
Stack.of(source(), "foobar").forEach(x => sink(x)); // NOT OK
51+
52+
List.of(source()).filter(x => true).toList().forEach(x => sink(x)); // NOT OK
53+
54+
Set.of(source()).filter(x => true).toList().forEach(x => sink(x)); // NOT OK
55+
56+
Set([source()]).filter(x => true).toList().forEach(x => sink(x)); // NOT OK
57+
58+
OrderedSet([source()]).filter(x => true).toList().forEach(x => sink(x)); // NOT OK

javascript/ql/test/library-tests/frameworks/Immutable/tests.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@
1515
| immutable.js:39:58:39:65 | source() | immutable.js:41:6:41:18 | map5.get("b") |
1616
| immutable.js:44:40:44:47 | source() | immutable.js:45:6:45:18 | map6.get("a") |
1717
| immutable.js:47:33:47:40 | source() | immutable.js:48:6:48:18 | map7.get("b") |
18+
| immutable.js:50:10:50:17 | source() | immutable.js:50:48:50:48 | x |
19+
| immutable.js:52:9:52:16 | source() | immutable.js:52:64:52:64 | x |
20+
| immutable.js:54:8:54:15 | source() | immutable.js:54:63:54:63 | x |
21+
| immutable.js:56:6:56:13 | source() | immutable.js:56:62:56:62 | x |
22+
| immutable.js:58:13:58:20 | source() | immutable.js:58:69:58:69 | x |

0 commit comments

Comments
 (0)