Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fe0b6a8

Browse files
committed
add data-flow steps for when Promise handlers return other promises
1 parent d8b25ef commit fe0b6a8

3 files changed

Lines changed: 82 additions & 1 deletion

File tree

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ private module PromiseFlow {
227227
prop = rejectField() and
228228
pred = getReceiver() and
229229
succ = this
230+
or
231+
// read the value of a resolved/rejected promise that is returned
232+
(prop = rejectField() or prop = resolveField()) and
233+
pred = getCallback(0).getAReturn() and
234+
succ = this
230235
}
231236

232237
override predicate store(DataFlow::Node pred, DataFlow::Node succ, string prop) {
@@ -258,6 +263,11 @@ private module PromiseFlow {
258263
prop = resolveField() and
259264
pred = getReceiver().getALocalSource() and
260265
succ = this
266+
or
267+
// read the value of a resolved/rejected promise that is returned
268+
(prop = rejectField() or prop = resolveField()) and
269+
pred = getCallback(0).getAReturn() and
270+
succ = this
261271
}
262272

263273
override predicate store(DataFlow::Node pred, DataFlow::Node succ, string prop) {
@@ -283,9 +293,13 @@ private module PromiseFlow {
283293
(prop = resolveField() or prop = rejectField()) and
284294
pred = getReceiver() and
285295
succ = this
296+
or
297+
// read the value of a rejected promise that is returned
298+
prop = rejectField() and
299+
pred = getCallback(0).getAReturn() and
300+
succ = this
286301
}
287302

288-
// a similar thing can also happen if a rejected promise is returned.
289303
override predicate store(DataFlow::Node pred, DataFlow::Node succ, string prop) {
290304
prop = rejectField() and
291305
pred = getCallback(0).getExceptionalReturn() and

javascript/ql/test/library-tests/Promises/flow.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,26 @@
103103
new Promise((resolve, reject) => reject("BLA")).catch(x => {return source}).then(x => sink(x)); // NOT OK
104104

105105
new Promise((resolve, reject) => reject("BLA")).finally(x => {throw source}).catch(x => sink(x)); // NOT OK
106+
107+
var rejected = new Promise((resolve, reject) => reject(source));
108+
109+
new Promise((resolve, reject) => reject("BLA")).finally(x => rejected).catch(x => sink(x)); // NOT OK
110+
111+
new Promise((resolve, reject) => reject("BLA")).catch(x => rejected).then(x => sink(x)) // OK
112+
113+
new Promise((resolve, reject) => reject("BLA")).catch(x => rejected).catch(x => sink(x)) // NOT OK
114+
115+
var resolved = Promise.resolve(source);
116+
117+
new Promise((resolve, reject) => reject("BLA")).catch(x => resolved).catch(x => sink(x)) // OK
118+
119+
new Promise((resolve, reject) => reject("BLA")).catch(x => resolved).then(x => sink(x)) // NOT OK
120+
121+
Promise.resolve(123).then(x => resolved).catch(x => sink(x)) // OK
122+
123+
Promise.resolve(123).then(x => resolved).then(x => sink(x)) // NOT OK
124+
125+
Promise.resolve(123).then(x => rejected).catch(x => sink(x)) // NOT OK
126+
127+
Promise.resolve(123).then(x => rejected).then(x => sink(x)) // OK
106128
})();

javascript/ql/test/library-tests/Promises/tests.expected

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ test_ResolvedPromiseDefinition
1010
| flow.js:46:2:46:24 | Promise ... source) | flow.js:46:18:46:23 | source |
1111
| flow.js:51:10:51:29 | Promise.resolve(src) | flow.js:51:26:51:28 | src |
1212
| flow.js:81:23:81:45 | Promise ... source) | flow.js:81:39:81:44 | source |
13+
| flow.js:115:17:115:39 | Promise ... source) | flow.js:115:33:115:38 | source |
14+
| flow.js:121:2:121:21 | Promise.resolve(123) | flow.js:121:18:121:20 | 123 |
15+
| flow.js:123:2:123:21 | Promise.resolve(123) | flow.js:123:18:123:20 | 123 |
16+
| flow.js:125:2:125:21 | Promise.resolve(123) | flow.js:125:18:125:20 | 123 |
17+
| flow.js:127:2:127:21 | Promise.resolve(123) | flow.js:127:18:127:20 | 123 |
1318
| promises.js:53:19:53:41 | Promise ... source) | promises.js:53:35:53:40 | source |
1419
| promises.js:62:19:62:41 | Promise ... source) | promises.js:62:35:62:40 | source |
1520
| promises.js:71:5:71:27 | Promise ... source) | promises.js:71:21:71:26 | source |
@@ -20,6 +25,11 @@ test_PromiseDefinition_getARejectHandler
2025
| flow.js:48:2:48:36 | new Pro ... urce }) | flow.js:48:44:48:55 | x => sink(x) |
2126
| flow.js:103:2:103:48 | new Pro ... "BLA")) | flow.js:103:56:103:75 | x => {return source} |
2227
| flow.js:105:2:105:48 | new Pro ... "BLA")) | flow.js:105:58:105:76 | x => {throw source} |
28+
| flow.js:109:2:109:48 | new Pro ... "BLA")) | flow.js:109:58:109:70 | x => rejected |
29+
| flow.js:111:2:111:48 | new Pro ... "BLA")) | flow.js:111:56:111:68 | x => rejected |
30+
| flow.js:113:2:113:48 | new Pro ... "BLA")) | flow.js:113:56:113:68 | x => rejected |
31+
| flow.js:117:2:117:48 | new Pro ... "BLA")) | flow.js:117:56:117:68 | x => resolved |
32+
| flow.js:119:2:119:48 | new Pro ... "BLA")) | flow.js:119:56:119:68 | x => resolved |
2333
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:20:6:22:3 | (v) => ... v;\\n } |
2434
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:23:18:25:3 | (v) => ... v;\\n } |
2535
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:26:20:28:3 | (v) => ... v;\\n } |
@@ -42,13 +52,20 @@ test_PromiseDefinition_getExecutor
4252
| flow.js:100:28:100:75 | new Pro ... ource)) | flow.js:100:40:100:74 | (resolv ... source) |
4353
| flow.js:103:2:103:48 | new Pro ... "BLA")) | flow.js:103:14:103:47 | (resolv ... ("BLA") |
4454
| flow.js:105:2:105:48 | new Pro ... "BLA")) | flow.js:105:14:105:47 | (resolv ... ("BLA") |
55+
| flow.js:107:17:107:64 | new Pro ... ource)) | flow.js:107:29:107:63 | (resolv ... source) |
56+
| flow.js:109:2:109:48 | new Pro ... "BLA")) | flow.js:109:14:109:47 | (resolv ... ("BLA") |
57+
| flow.js:111:2:111:48 | new Pro ... "BLA")) | flow.js:111:14:111:47 | (resolv ... ("BLA") |
58+
| flow.js:113:2:113:48 | new Pro ... "BLA")) | flow.js:113:14:113:47 | (resolv ... ("BLA") |
59+
| flow.js:117:2:117:48 | new Pro ... "BLA")) | flow.js:117:14:117:47 | (resolv ... ("BLA") |
60+
| flow.js:119:2:119:48 | new Pro ... "BLA")) | flow.js:119:14:119:47 | (resolv ... ("BLA") |
4561
| interflow.js:11:12:15:6 | new Pro ... \\n }) | interflow.js:11:24:15:5 | functio ... ;\\n } |
4662
| promises.js:3:17:5:4 | new Pro ... );\\n }) | promises.js:3:29:5:3 | functio ... e);\\n } |
4763
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:10:30:17:3 | (res, r ... e);\\n } |
4864
| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:33:31:35:5 | functio ... ;\\n } |
4965
| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:43:29:45:5 | functio ... ;\\n } |
5066
test_PromiseDefinition_getAFinallyHandler
5167
| flow.js:105:2:105:48 | new Pro ... "BLA")) | flow.js:105:58:105:76 | x => {throw source} |
68+
| flow.js:109:2:109:48 | new Pro ... "BLA")) | flow.js:109:58:109:70 | x => rejected |
5269
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:26:20:28:3 | (v) => ... v;\\n } |
5370
test_PromiseDefinition
5471
| flow.js:7:11:7:59 | new Pro ... ource)) |
@@ -69,6 +86,12 @@ test_PromiseDefinition
6986
| flow.js:100:28:100:75 | new Pro ... ource)) |
7087
| flow.js:103:2:103:48 | new Pro ... "BLA")) |
7188
| flow.js:105:2:105:48 | new Pro ... "BLA")) |
89+
| flow.js:107:17:107:64 | new Pro ... ource)) |
90+
| flow.js:109:2:109:48 | new Pro ... "BLA")) |
91+
| flow.js:111:2:111:48 | new Pro ... "BLA")) |
92+
| flow.js:113:2:113:48 | new Pro ... "BLA")) |
93+
| flow.js:117:2:117:48 | new Pro ... "BLA")) |
94+
| flow.js:119:2:119:48 | new Pro ... "BLA")) |
7295
| interflow.js:11:12:15:6 | new Pro ... \\n }) |
7396
| promises.js:3:17:5:4 | new Pro ... );\\n }) |
7497
| promises.js:10:18:17:4 | new Pro ... );\\n }) |
@@ -84,6 +107,7 @@ test_PromiseDefinition_getAResolveHandler
84107
| flow.js:74:10:74:57 | new Pro ... ource)) | flow.js:74:64:74:71 | () => {} |
85108
| flow.js:91:21:91:68 | new Pro ... ource)) | flow.js:91:75:91:82 | () => {} |
86109
| flow.js:105:2:105:48 | new Pro ... "BLA")) | flow.js:105:58:105:76 | x => {throw source} |
110+
| flow.js:109:2:109:48 | new Pro ... "BLA")) | flow.js:109:58:109:70 | x => rejected |
87111
| promises.js:3:17:5:4 | new Pro ... );\\n }) | promises.js:6:16:8:3 | functio ... al;\\n } |
88112
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:18:17:20:3 | (v) => ... v;\\n } |
89113
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:26:20:28:3 | (v) => ... v;\\n } |
@@ -107,6 +131,12 @@ test_PromiseDefinition_getRejectParameter
107131
| flow.js:100:28:100:75 | new Pro ... ource)) | flow.js:100:50:100:55 | reject |
108132
| flow.js:103:2:103:48 | new Pro ... "BLA")) | flow.js:103:24:103:29 | reject |
109133
| flow.js:105:2:105:48 | new Pro ... "BLA")) | flow.js:105:24:105:29 | reject |
134+
| flow.js:107:17:107:64 | new Pro ... ource)) | flow.js:107:39:107:44 | reject |
135+
| flow.js:109:2:109:48 | new Pro ... "BLA")) | flow.js:109:24:109:29 | reject |
136+
| flow.js:111:2:111:48 | new Pro ... "BLA")) | flow.js:111:24:111:29 | reject |
137+
| flow.js:113:2:113:48 | new Pro ... "BLA")) | flow.js:113:24:113:29 | reject |
138+
| flow.js:117:2:117:48 | new Pro ... "BLA")) | flow.js:117:24:117:29 | reject |
139+
| flow.js:119:2:119:48 | new Pro ... "BLA")) | flow.js:119:24:119:29 | reject |
110140
| interflow.js:11:12:15:6 | new Pro ... \\n }) | interflow.js:11:43:11:48 | reject |
111141
| promises.js:3:17:5:4 | new Pro ... );\\n }) | promises.js:3:48:3:53 | reject |
112142
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:10:36:10:38 | rej |
@@ -130,6 +160,12 @@ test_PromiseDefinition_getResolveParameter
130160
| flow.js:100:28:100:75 | new Pro ... ource)) | flow.js:100:41:100:47 | resolve |
131161
| flow.js:103:2:103:48 | new Pro ... "BLA")) | flow.js:103:15:103:21 | resolve |
132162
| flow.js:105:2:105:48 | new Pro ... "BLA")) | flow.js:105:15:105:21 | resolve |
163+
| flow.js:107:17:107:64 | new Pro ... ource)) | flow.js:107:30:107:36 | resolve |
164+
| flow.js:109:2:109:48 | new Pro ... "BLA")) | flow.js:109:15:109:21 | resolve |
165+
| flow.js:111:2:111:48 | new Pro ... "BLA")) | flow.js:111:15:111:21 | resolve |
166+
| flow.js:113:2:113:48 | new Pro ... "BLA")) | flow.js:113:15:113:21 | resolve |
167+
| flow.js:117:2:117:48 | new Pro ... "BLA")) | flow.js:117:15:117:21 | resolve |
168+
| flow.js:119:2:119:48 | new Pro ... "BLA")) | flow.js:119:15:119:21 | resolve |
133169
| interflow.js:11:12:15:6 | new Pro ... \\n }) | interflow.js:11:34:11:40 | resolve |
134170
| promises.js:3:17:5:4 | new Pro ... );\\n }) | promises.js:3:39:3:45 | resolve |
135171
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:10:31:10:33 | res |
@@ -139,6 +175,10 @@ test_PromiseDefinition_getACatchHandler
139175
| flow.js:32:2:32:49 | new Pro ... ource)) | flow.js:32:57:32:68 | x => sink(x) |
140176
| flow.js:48:2:48:36 | new Pro ... urce }) | flow.js:48:44:48:55 | x => sink(x) |
141177
| flow.js:103:2:103:48 | new Pro ... "BLA")) | flow.js:103:56:103:75 | x => {return source} |
178+
| flow.js:111:2:111:48 | new Pro ... "BLA")) | flow.js:111:56:111:68 | x => rejected |
179+
| flow.js:113:2:113:48 | new Pro ... "BLA")) | flow.js:113:56:113:68 | x => rejected |
180+
| flow.js:117:2:117:48 | new Pro ... "BLA")) | flow.js:117:56:117:68 | x => resolved |
181+
| flow.js:119:2:119:48 | new Pro ... "BLA")) | flow.js:119:56:119:68 | x => resolved |
142182
| promises.js:10:18:17:4 | new Pro ... );\\n }) | promises.js:23:18:25:3 | (v) => ... v;\\n } |
143183
flow
144184
| flow.js:2:15:2:22 | "source" | flow.js:5:7:5:14 | await p1 |
@@ -165,4 +205,9 @@ flow
165205
| flow.js:2:15:2:22 | "source" | flow.js:101:7:101:9 | foo |
166206
| flow.js:2:15:2:22 | "source" | flow.js:103:93:103:93 | x |
167207
| flow.js:2:15:2:22 | "source" | flow.js:105:95:105:95 | x |
208+
| flow.js:2:15:2:22 | "source" | flow.js:109:89:109:89 | x |
209+
| flow.js:2:15:2:22 | "source" | flow.js:113:87:113:87 | x |
210+
| flow.js:2:15:2:22 | "source" | flow.js:119:86:119:86 | x |
211+
| flow.js:2:15:2:22 | "source" | flow.js:123:58:123:58 | x |
212+
| flow.js:2:15:2:22 | "source" | flow.js:125:59:125:59 | x |
168213
| interflow.js:3:18:3:25 | "source" | interflow.js:18:10:18:14 | error |

0 commit comments

Comments
 (0)