JS: Port Promises test

Result changes are benign
This commit is contained in:
Asger F
2023-10-06 10:39:19 +02:00
parent dd8a24c6c0
commit 81bd292a16
4 changed files with 45 additions and 20 deletions

View File

@@ -65,7 +65,7 @@
await new Promise((resolve, reject) => reject(source));
}
try {
throws();
await throws();
} catch(e) {
sink(e); // NOT OK!
}

View File

@@ -1,39 +1,60 @@
import javascript
private import semmle.javascript.dataflow.internal.StepSummary
import testUtilities.LegacyDataFlowDiff
class Configuration extends DataFlow::Configuration {
Configuration() { this = "PromiseDataFlowFlowTestingConfig" }
override predicate isSource(DataFlow::Node source) {
module ValueFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getEnclosingExpr().getStringValue() = "source"
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
any(DataFlow::InvokeNode call | call.getCalleeName() = "sink").getAnArgument() = sink
}
}
class TaintConfig extends TaintTracking::Configuration {
TaintConfig() { this = "PromiseTaintFlowTestingConfig" }
module ValueFlow = DataFlow::Global<ValueFlowConfig>;
override predicate isSource(DataFlow::Node source) {
module TaintConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.getEnclosingExpr().getStringValue() = "source"
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
any(DataFlow::InvokeNode call | call.getCalleeName() = "sink").getAnArgument() = sink
}
}
query predicate flow(DataFlow::Node source, DataFlow::Node sink) {
any(Configuration c).hasFlow(source, sink)
}
module TaintFlow = TaintTracking::Global<TaintConfig>;
query predicate flow(DataFlow::Node source, DataFlow::Node sink) { ValueFlow::flow(source, sink) }
query predicate exclusiveTaintFlow(DataFlow::Node source, DataFlow::Node sink) {
not any(Configuration c).hasFlow(source, sink) and
any(TaintConfig c).hasFlow(source, sink)
not ValueFlow::flow(source, sink) and
TaintFlow::flow(source, sink)
}
query predicate typetrack(DataFlow::SourceNode succ, DataFlow::SourceNode pred, StepSummary summary) {
succ = PromiseTypeTracking::promiseStep(pred, summary)
}
class LegacyValueConfig extends DataFlow::Configuration {
LegacyValueConfig() { this = "LegacyValueConfig" }
override predicate isSource(DataFlow::Node source) { ValueFlowConfig::isSource(source) }
override predicate isSink(DataFlow::Node sink) { ValueFlowConfig::isSink(sink) }
}
query predicate valueFlowDifference =
DataFlowDiff<ValueFlow, LegacyValueConfig>::legacyDataFlowDifference/3;
class LegacyTaintConfig extends TaintTracking::Configuration {
LegacyTaintConfig() { this = "LegacyTaintConfig" }
override predicate isSource(DataFlow::Node source) { TaintConfig::isSource(source) }
override predicate isSink(DataFlow::Node sink) { TaintConfig::isSink(sink) }
}
query predicate taintFlowDifference =
DataFlowDiff<TaintFlow, LegacyTaintConfig>::legacyDataFlowDifference/3;

View File

@@ -17,11 +17,11 @@
var [clean3, tainted3] = await Promise.all(["clean", Promise.resolve(source)]);
sink(clean3); // OK
sink(tainted3); // NOT OK - but only flagged by taint-tracking
sink(tainted3); // NOT OK
var tainted4 = await Promise.race(["clean", Promise.resolve(source)]);
sink(tainted4); // NOT OK - but only flagged by taint-tracking
sink(tainted4); // NOT OK
var tainted5 = await Promise.any(["clean", Promise.resolve(source)]);
sink(tainted5); // NOT OK - but only flagged by taint-tracking
});
sink(tainted5); // NOT OK
});

View File

@@ -237,6 +237,7 @@ flow
| flow2.js:2:15:2:22 | "source" | flow2.js:6:8:6:13 | arr[0] |
| flow2.js:2:15:2:22 | "source" | flow2.js:12:7:12:13 | tainted |
| flow2.js:2:15:2:22 | "source" | flow2.js:16:7:16:14 | tainted2 |
| flow2.js:2:15:2:22 | "source" | flow2.js:20:7:20:14 | tainted3 |
| flow2.js:2:15:2:22 | "source" | flow2.js:23:7:23:14 | tainted4 |
| flow2.js:2:15:2:22 | "source" | flow2.js:26:7:26:14 | tainted5 |
| flow.js:2:15:2:22 | "source" | flow.js:5:7:5:14 | await p1 |
@@ -273,7 +274,6 @@ flow
| flow.js:136:15:136:22 | "source" | flow.js:142:7:142:19 | await async() |
| flow.js:136:15:136:22 | "source" | flow.js:155:9:155:9 | e |
exclusiveTaintFlow
| flow2.js:2:15:2:22 | "source" | flow2.js:20:7:20:14 | tainted3 |
| flow.js:136:15:136:22 | "source" | flow.js:141:7:141:13 | async() |
| flow.js:160:15:160:22 | "source" | flow.js:164:39:164:39 | x |
| flow.js:160:15:160:22 | "source" | flow.js:167:7:167:9 | foo |
@@ -367,6 +367,7 @@ typetrack
| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | copy $PromiseResolveField$ |
| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | store $PromiseResolveField$ |
| flow.js:65:3:65:56 | await n ... ource)) | flow.js:65:9:65:56 | new Pro ... ource)) | load $PromiseResolveField$ |
| flow.js:68:3:68:16 | await throws() | flow.js:68:9:68:16 | throws() | load $PromiseResolveField$ |
| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:2:76:32 | chained ... => {}) | copy $PromiseResolveField$ |
| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | copy $PromiseResolveField$ |
| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | store $PromiseResolveField$ |
@@ -462,3 +463,6 @@ typetrack
| promises.js:143:17:143:50 | Synchro ... source) | promises.js:143:44:143:49 | source | store $PromiseResolveField$ |
| promises.js:153:17:153:39 | Promise ... source) | promises.js:153:33:153:38 | source | copy $PromiseResolveField$ |
| promises.js:153:17:153:39 | Promise ... source) | promises.js:153:33:153:38 | source | store $PromiseResolveField$ |
valueFlowDifference
| flow2.js:2:15:2:22 | "source" | flow2.js:20:7:20:14 | tainted3 | only flow with NEW data flow library |
taintFlowDifference