@@ -120,50 +120,56 @@ class AggregateES2015PromiseDefinition extends PromiseCreationCall {
120120 }
121121}
122122
123+ /**
124+ * Common predicates shared between type-tracking and data-flow for promises.
125+ */
126+ module Promises {
127+ /**
128+ * Gets the pseudo-field used to describe resolved values in a promise.
129+ */
130+ string valueProp ( ) { result = "$PromiseResolveField$" }
131+
132+ /**
133+ * Gets the pseudo-field used to describe rejected values in a promise.
134+ */
135+ string errorProp ( ) { result = "$PromiseRejectField$" }
136+ }
137+
123138/**
124139 * A module for supporting promises in type-tracking predicates.
125- * The `PromiseTypeTracking::promiseStep` predicate can be used to add type-tracking in and out of promises,
126- * and the `PromiseTypeTracking::valueInPromiseTracker` predicate can be used to initiate a type-tracker
127- * where the tracked value is inside a promise.
140+ * The `PromiseTypeTracking::promiseStep` is used for type tracking in and out of promises,
141+ * and is included in the standard type-tracking steps (`SourceNode::track`).
142+ * The `TypeTracker::startInPromise()` predicate can be used to initiate a type-tracker
143+ * where the tracked value is a promise.
128144 *
129- * The below is an example of a type-tracking predicate where the initial value is inside a promise:
145+ * The below is an example of a type-tracking predicate where the initial value is a promise:
130146 * ```
131147 * DataFlow::SourceNode myType(DataFlow::TypeTracker t) {
132- * t = PromiseTypeTracking::valueInPromiseTracker()
148+ * t.startInPromise() and
133149 * result = <the promise value> and
134150 * or
135151 * exists(DataFlow::TypeTracker t2 | result = myType(t2).track(t2, t))
136- * or
137- * exists(DataFlow::TypeTracker t2, DataFlow::StepSummary summary |
138- * result = PromiseTypeTracking::promiseStep(myType(t2), summary) and
139- * t = t2.append(summary)
140- * )
141152 * }
142153 * ```
143- * The above example uses all the standard type-tracking steps and the promise specific type-tracking steps.
144- * The standard type-tracking steps can be removed for a type-tracking predicate that only tracks flow out of a promise.
154+ *
155+ * The type-tracking predicate above will only end (`t = DataFlow::TypeTracker::end()`) after the tracked value has been
156+ * extracted from the promise.
157+ *
158+ * The `PromiseTypeTracking::promiseStep` predicate can be used instead of `SourceNode::track`
159+ * to get type-tracking only for promise steps.
145160 *
146- * Replace `t = PromiseTypeTracking::valueInPromiseTracker ()` in the above example with `t.start()` to create a type-tracking predicate
161+ * Replace `t.startInPromise ()` in the above example with `t.start()` to create a type-tracking predicate
147162 * where the value is not initially inside a promise.
148163 */
149164module PromiseTypeTracking {
150- /**
151- * A type-tracker used to start a type-tracker where the tracked value is initially inside a promise.
152- */
153- DataFlow:: TypeTracker valueInPromiseTracker ( ) {
154- exists ( DataFlow:: TypeTracker start | start .start ( ) |
155- result = start .append ( DataFlow:: StoreStep ( resolveField ( ) ) )
156- )
157- }
158-
159165 /**
160166 * Gets the result from a single step through a promise, from `pred` to `result` summarized by `summary`.
161167 * This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another.
162168 *
163169 * See the qldoc for the `PromiseTypeTracking` module for an example of how to use this predicate.
164170 */
165171 DataFlow:: SourceNode promiseStep ( DataFlow:: SourceNode pred , DataFlow:: StepSummary summary ) {
166- exists ( PromiseFlowStep step , string field | field = resolveField ( ) |
172+ exists ( PromiseFlowStep step , string field | field = Promises :: valueProp ( ) |
167173 summary = DataFlow:: LoadStep ( field ) and
168174 step .load ( pred , result , field )
169175 or
@@ -179,14 +185,14 @@ module PromiseTypeTracking {
179185 * A class enabling the use of the `resolveField` as a pseudo-property in type-tracking predicates.
180186 */
181187 private class ResolveFieldAsTypeTrackingProperty extends DataFlow:: TypeTrackingPseudoProperty {
182- ResolveFieldAsTypeTrackingProperty ( ) { this = resolveField ( ) }
188+ ResolveFieldAsTypeTrackingProperty ( ) { this = Promises :: valueProp ( ) }
183189 }
184190}
185191
186192/**
187193 * An `AdditionalFlowStep` used to model a data-flow step related to promises.
188194 *
189- * The `loadStep`/`storeStep`/`loadStoreStep` methods are overloaded such that the new overloads
195+ * The `loadStep`/`storeStep`/`loadStoreStep` methods are overloaded such that the new predicates
190196 * `load`/`store`/`loadStore` can be used in the `PromiseTypeTracking` module.
191197 * (Thereby avoiding conflicts with a "cousin" `AdditionalFlowStep` implementation.)
192198 *
@@ -229,20 +235,13 @@ abstract private class PromiseFlowStep extends DataFlow::AdditionalFlowStep {
229235 }
230236}
231237
232- /**
233- * Gets the pseudo-field used to describe resolved values in a promise.
234- */
235- private string resolveField ( ) { result = "$PromiseResolveField$" }
236-
237238/**
238239 * This module defines how data-flow propagates into and out of a Promise.
239240 * The data-flow is based on pseudo-properties rather than tainting the Promise object (which is what `PromiseTaintStep` does).
240241 */
241242private module PromiseFlow {
242- /**
243- * Gets the pseudo-field used to describe rejected values in a promise.
244- */
245- string rejectField ( ) { result = "$PromiseRejectField$" }
243+ private predicate valueProp = Promises:: valueProp / 0 ;
244+ private predicate errorProp = Promises:: errorProp / 0 ;
246245
247246 /**
248247 * A flow step describing a promise definition.
@@ -255,11 +254,11 @@ private module PromiseFlow {
255254 PromiseDefitionStep ( ) { this = promise }
256255
257256 override predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
258- prop = resolveField ( ) and
257+ prop = valueProp ( ) and
259258 pred = promise .getResolveParameter ( ) .getACall ( ) .getArgument ( 0 ) and
260259 succ = this
261260 or
262- prop = rejectField ( ) and
261+ prop = errorProp ( ) and
263262 (
264263 pred = promise .getRejectParameter ( ) .getACall ( ) .getArgument ( 0 ) or
265264 pred = promise .getExecutor ( ) .getExceptionalReturn ( )
@@ -269,7 +268,7 @@ private module PromiseFlow {
269268
270269 override predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
271270 // Copy the value of a resolved promise to the value of this promise.
272- prop = resolveField ( ) and
271+ prop = valueProp ( ) and
273272 pred = promise .getResolveParameter ( ) .getACall ( ) .getArgument ( 0 ) and
274273 succ = this
275274 }
@@ -284,14 +283,14 @@ private module PromiseFlow {
284283 CreationStep ( ) { this = promise }
285284
286285 override predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
287- prop = resolveField ( ) and
286+ prop = valueProp ( ) and
288287 pred = promise .getValue ( ) and
289288 succ = this
290289 }
291290
292291 override predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
293292 // Copy the value of a resolved promise to the value of this promise.
294- prop = resolveField ( ) and
293+ prop = valueProp ( ) and
295294 pred = promise .getValue ( ) and
296295 succ = this
297296 }
@@ -311,11 +310,11 @@ private module PromiseFlow {
311310 }
312311
313312 override predicate load ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
314- prop = resolveField ( ) and
313+ prop = valueProp ( ) and
315314 succ = this and
316315 pred = operand
317316 or
318- prop = rejectField ( ) and
317+ prop = errorProp ( ) and
319318 succ = await .getExceptionTarget ( ) and
320319 pred = operand
321320 }
@@ -328,33 +327,33 @@ private module PromiseFlow {
328327 ThenStep ( ) { this .getMethodName ( ) = "then" }
329328
330329 override predicate load ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
331- prop = resolveField ( ) and
330+ prop = valueProp ( ) and
332331 pred = getReceiver ( ) and
333332 succ = getCallback ( 0 ) .getParameter ( 0 )
334333 or
335- prop = rejectField ( ) and
334+ prop = errorProp ( ) and
336335 pred = getReceiver ( ) and
337336 succ = getCallback ( 1 ) .getParameter ( 0 )
338337 }
339338
340339 override predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
341340 not exists ( this .getArgument ( 1 ) ) and
342- prop = rejectField ( ) and
341+ prop = errorProp ( ) and
343342 pred = getReceiver ( ) and
344343 succ = this
345344 or
346345 // read the value of a resolved/rejected promise that is returned
347- ( prop = rejectField ( ) or prop = resolveField ( ) ) and
346+ ( prop = errorProp ( ) or prop = valueProp ( ) ) and
348347 pred = getCallback ( [ 0 .. 1 ] ) .getAReturn ( ) and
349348 succ = this
350349 }
351350
352351 override predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
353- prop = resolveField ( ) and
352+ prop = valueProp ( ) and
354353 pred = getCallback ( [ 0 .. 1 ] ) .getAReturn ( ) and
355354 succ = this
356355 or
357- prop = rejectField ( ) and
356+ prop = errorProp ( ) and
358357 pred = getCallback ( [ 0 .. 1 ] ) .getExceptionalReturn ( ) and
359358 succ = this
360359 }
@@ -367,28 +366,28 @@ private module PromiseFlow {
367366 CatchStep ( ) { this .getMethodName ( ) = "catch" }
368367
369368 override predicate load ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
370- prop = rejectField ( ) and
369+ prop = errorProp ( ) and
371370 pred = getReceiver ( ) and
372371 succ = getCallback ( 0 ) .getParameter ( 0 )
373372 }
374373
375374 override predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
376- prop = resolveField ( ) and
375+ prop = valueProp ( ) and
377376 pred = getReceiver ( ) .getALocalSource ( ) and
378377 succ = this
379378 or
380379 // read the value of a resolved/rejected promise that is returned
381- ( prop = rejectField ( ) or prop = resolveField ( ) ) and
380+ ( prop = errorProp ( ) or prop = valueProp ( ) ) and
382381 pred = getCallback ( 0 ) .getAReturn ( ) and
383382 succ = this
384383 }
385384
386385 override predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
387- prop = rejectField ( ) and
386+ prop = errorProp ( ) and
388387 pred = getCallback ( 0 ) .getExceptionalReturn ( ) and
389388 succ = this
390389 or
391- prop = resolveField ( ) and
390+ prop = valueProp ( ) and
392391 pred = getCallback ( 0 ) .getAReturn ( ) and
393392 succ = this
394393 }
@@ -401,18 +400,18 @@ private module PromiseFlow {
401400 FinallyStep ( ) { this .getMethodName ( ) = "finally" }
402401
403402 override predicate loadStore ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
404- ( prop = resolveField ( ) or prop = rejectField ( ) ) and
403+ ( prop = valueProp ( ) or prop = errorProp ( ) ) and
405404 pred = getReceiver ( ) and
406405 succ = this
407406 or
408407 // read the value of a rejected promise that is returned
409- prop = rejectField ( ) and
408+ prop = errorProp ( ) and
410409 pred = getCallback ( 0 ) .getAReturn ( ) and
411410 succ = this
412411 }
413412
414413 override predicate store ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
415- prop = rejectField ( ) and
414+ prop = errorProp ( ) and
416415 pred = getCallback ( 0 ) .getExceptionalReturn ( ) and
417416 succ = this
418417 }
0 commit comments