Skip to content

Commit 9a8cb1a

Browse files
authored
Merge pull request #19007 from asgerf/js/api-graph-awaited-return
JS: Fix bug in API graphs getPromised() missing async function returns
2 parents cf0b3b5 + 08ee51c commit 9a8cb1a

File tree

2 files changed

+38
-24
lines changed

2 files changed

+38
-24
lines changed

javascript/ql/lib/semmle/javascript/Promises.qll

+12-24
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import javascript
66
private import dataflow.internal.StepSummary
7+
private import semmle.javascript.dataflow.internal.FlowSteps
78

89
/**
910
* A call to the `Promise` constructor, such as `new Promise((resolve, reject) => { ... })`.
@@ -397,6 +398,17 @@ module PromiseFlow {
397398
value = call.getCallback(0).getExceptionalReturn() and
398399
obj = call
399400
)
401+
or
402+
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
403+
// ordinary return
404+
prop = valueProp() and
405+
value = f.getAReturn() and
406+
obj = f.getReturnNode()
407+
or
408+
// exceptional return
409+
prop = errorProp() and
410+
localExceptionStepWithAsyncFlag(value, obj, true)
411+
)
400412
}
401413

402414
/**
@@ -525,30 +537,6 @@ private class PromiseTaintStep extends TaintTracking::LegacyTaintStep {
525537
* Defines flow steps for return on async functions.
526538
*/
527539
private module AsyncReturnSteps {
528-
private predicate valueProp = Promises::valueProp/0;
529-
530-
private predicate errorProp = Promises::errorProp/0;
531-
532-
private import semmle.javascript.dataflow.internal.FlowSteps
533-
534-
/**
535-
* A data-flow step for ordinary and exceptional returns from async functions.
536-
*/
537-
private class AsyncReturn extends LegacyPreCallGraphStep {
538-
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
539-
exists(DataFlow::FunctionNode f | f.getFunction().isAsync() |
540-
// ordinary return
541-
prop = valueProp() and
542-
pred = f.getAReturn() and
543-
succ = f.getReturnNode()
544-
or
545-
// exceptional return
546-
prop = errorProp() and
547-
localExceptionStepWithAsyncFlag(pred, succ, true)
548-
)
549-
}
550-
}
551-
552540
/**
553541
* A data-flow step for ordinary return from an async function in a taint configuration.
554542
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as t from "testlib";
2+
3+
async function getData1() {
4+
const data = await fetch("https://example.com/content");
5+
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
6+
}
7+
8+
export function use1() {
9+
t.foo(() => getData1());
10+
}
11+
12+
async function getData2() {
13+
const data = await fetch("https://example.com/content");
14+
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
15+
}
16+
17+
export function use2() {
18+
t.foo(getData2);
19+
}
20+
21+
export function use3() {
22+
t.foo(async () => {
23+
const data = await fetch("https://example.com/content");
24+
return data.json(); /* def=moduleImport("testlib").getMember("exports").getMember("foo").getParameter(0).getReturn().getPromised() */
25+
});
26+
}

0 commit comments

Comments
 (0)