support toJS() by using plain property names instead of pseudoproperties.

This commit is contained in:
Erik Krogh Kristensen
2021-02-03 19:46:16 +01:00
parent b1f092f052
commit 6cbe4caecc
3 changed files with 22 additions and 12 deletions

View File

@@ -8,8 +8,6 @@ import javascript
* Provides classes implementing data-flow for Immutable.
*/
private module Immutable {
private import DataFlow::PseudoProperties
/**
* An API entrypoint for the global `Immutable` variable.
*/
@@ -40,33 +38,35 @@ private module Immutable {
}
/**
* Gets the immutable collection where `pred` has been stored using the pseudoproperty `prop`.
* An instance of any immutable collection.
*/
API::Node immutableCollection() { result = immutableMap() }
/**
* Gets the immutable collection where `pred` has been stored using the name `prop`.
*/
DataFlow::SourceNode storeStep(DataFlow::Node pred, string prop) {
exists(DataFlow::CallNode call, string key |
call = immutableImport().getMember("Map").getACall()
|
prop = mapValueKey(key) and
pred = call.getOptionArgument(0, key) and
exists(DataFlow::CallNode call | call = immutableImport().getMember("Map").getACall() |
pred = call.getOptionArgument(0, prop) and
result = call
)
or
exists(DataFlow::CallNode call | call = immutableMap().getMember("set").getACall() |
prop = mapValue(call.getArgument(0)) and
call.getArgument(0).mayHaveStringValue(prop) and
pred = call.getArgument(1) and
result = call
)
}
/**
* Gets the value that was stored in the immutable collection `pred` under the pseudoproperty `prop`.
* Gets the value that was stored in the immutable collection `pred` under the name `prop`.
*/
DataFlow::Node loadStep(DataFlow::Node pred, string prop) {
// map.get()
exists(DataFlow::MethodCallNode call | call = immutableMap().getMember("get").getACall() |
call.getArgument(0).mayHaveStringValue(prop) and
pred = call.getReceiver() and
result = call and
prop = mapValue(call.getArgument(0))
result = call
)
}
@@ -79,6 +79,12 @@ private module Immutable {
pred = call.getReceiver() and
result = call
)
or
// toJS() or any immutable collection converts it to a plain JavaScript object/array.
exists(DataFlow::CallNode call | call = immutableCollection().getMember("toJS").getACall() |
pred = call.getReceiver() and
result = call
)
}
/**

View File

@@ -15,3 +15,6 @@ sink(map2.get("b")); // OK - but still flagged [INCONSISTENCY]
const map3 = map2.set("d", source("d"));
sink(map1.get("d")); // OK
sink(map3.get("d")); // NOT OK
sink(map3.toJS()["a"]); // NOT OK

View File

@@ -1,6 +1,7 @@
| immutable.js:1:16:1:26 | source("a") | immutable.js:2:6:2:13 | obj["a"] |
| immutable.js:1:16:1:26 | source("a") | immutable.js:11:6:11:18 | map1.get("a") |
| immutable.js:1:16:1:26 | source("a") | immutable.js:12:6:12:18 | map2.get("a") |
| immutable.js:1:16:1:26 | source("a") | immutable.js:20:6:20:21 | map3.toJS()["a"] |
| immutable.js:1:32:1:43 | source("b1") | immutable.js:8:6:8:18 | map1.get("b") |
| immutable.js:1:32:1:43 | source("b1") | immutable.js:13:6:13:18 | map2.get("b") |
| immutable.js:15:28:15:38 | source("d") | immutable.js:17:6:17:18 | map3.get("d") |