Merge pull request #2967 from asger-semmle/js/flow-through-prop

Approved by esbena
This commit is contained in:
semmle-qlci
2020-03-05 09:46:35 +00:00
committed by GitHub
4 changed files with 100 additions and 2 deletions

View File

@@ -901,8 +901,14 @@ private predicate reachableFromStoreBase(
string prop, DataFlow::Node rhs, DataFlow::Node nd, DataFlow::Configuration cfg,
PathSummary summary
) {
isRelevant(rhs, cfg) and
storeStep(rhs, nd, prop, cfg, summary)
exists(PathSummary s1, PathSummary s2 |
reachableFromSource(rhs, cfg, s1)
or
reachableFromStoreBase(_, _, rhs, cfg, s1)
|
storeStep(rhs, nd, prop, cfg, s2) and
summary = MkPathSummary(false, s1.hasCall().booleanOr(s2.hasCall()), s2.getStartLabel(), s2.getEndLabel())
)
or
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) and

View File

@@ -67,6 +67,12 @@ typeInferenceMismatch
| exceptions.js:158:13:158:20 | source() | exceptions.js:161:10:161:10 | e |
| importedReactComponent.jsx:4:40:4:47 | source() | exportedReactComponent.jsx:2:10:2:19 | props.text |
| indexOf.js:4:11:4:18 | source() | indexOf.js:9:10:9:10 | x |
| nested-props.js:4:13:4:20 | source() | nested-props.js:5:10:5:14 | obj.x |
| nested-props.js:9:18:9:25 | source() | nested-props.js:10:10:10:16 | obj.x.y |
| nested-props.js:35:13:35:20 | source() | nested-props.js:36:10:36:20 | doLoad(obj) |
| nested-props.js:43:13:43:20 | source() | nested-props.js:44:10:44:18 | id(obj).x |
| nested-props.js:67:31:67:38 | source() | nested-props.js:68:10:68:10 | x |
| nested-props.js:77:36:77:43 | source() | nested-props.js:78:10:78:10 | x |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:17:14:17:14 | x |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:20:14:20:14 | y |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value |

View File

@@ -42,6 +42,11 @@
| exceptions.js:158:13:158:20 | source() | exceptions.js:161:10:161:10 | e |
| indexOf.js:4:11:4:18 | source() | indexOf.js:9:10:9:10 | x |
| indexOf.js:4:11:4:18 | source() | indexOf.js:13:10:13:10 | x |
| nested-props.js:4:13:4:20 | source() | nested-props.js:5:10:5:14 | obj.x |
| nested-props.js:9:18:9:25 | source() | nested-props.js:10:10:10:16 | obj.x.y |
| nested-props.js:35:13:35:20 | source() | nested-props.js:36:10:36:20 | doLoad(obj) |
| nested-props.js:43:13:43:20 | source() | nested-props.js:44:10:44:18 | id(obj).x |
| nested-props.js:67:31:67:38 | source() | nested-props.js:68:10:68:10 | x |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:17:14:17:14 | x |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:20:14:20:14 | y |
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value |

View File

@@ -0,0 +1,81 @@
import * as dummy from 'dummy';
function storeLoadFlow(obj) {
obj.x = source();
sink(obj.x); // NOT OK
}
function storeStoreLoadLoadFlow(obj) {
obj.x = { y: source() };
sink(obj.x.y); // NOT OK
}
function loadStoreFlow(obj) {
obj.x.y = source();
sink(obj.x.y); // NOT OK - but not found
}
function loadLoadStoreFlow(obj) {
obj.x.y.z = source();
sink(obj.x.y.z); // NOT OK - but not found
}
function doStore(obj, x) {
obj.x = x;
}
function callStoreBackcallFlow(obj) {
doStore(obj, source());
sink(obj.x); // NOT OK - but not found
}
function doLoad(obj) {
return obj.x
}
function storeCallLoadReturnFlow(obj) {
obj.x = source();
sink(doLoad(obj)); // NOT OK
}
function id(obj) {
return obj
}
function storeCallReturnLoadFlow(obj) {
obj.x = source();
sink(id(obj).x); // NOT OK
}
function doLoadStore(obj, val) {
obj.x.y = val;
}
function callStoreBackloadBackcallLoadLoad(obj) {
doLoadStore(obj, source());
sink(obj.x.y); // NOT OK - but not found
}
function doLoadLoad(obj) {
return obj.x.y
}
function storeBackloadCallLoadLoadReturn(obj) {
obj.x.y = source();
sink(doLoadStore(obj)); // NOT OK - but not found
}
function doStoreReturn(val) {
return { x: val }
}
function callStoreReturnLoad() {
let { x } = doStoreReturn(source());
sink(x); // NOT OK
doStoreReturn(null); // ensure multiple call sites exist
}
function doTaintStoreReturn(val) {
return { x: val + "!!" }
}
function callTaintStoreReturnLoadFlow() {
let { x } = doTaintStoreReturn(source());
sink(x); // NOT OK
doTaintStoreReturn(null); // ensure multiple call sites exist
}