Skip to content

Commit e831489

Browse files
committed
WIP: Factor out Promisification state
1 parent 4060c68 commit e831489

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,14 @@ module API {
11331133
// for fields and accessors, mark the reads as use-nodes
11341134
decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead))
11351135
)
1136+
or
1137+
// awaiting the return value from a promisified function
1138+
exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc, int boundArgs |
1139+
use(base, src) and
1140+
pred = trackUseNode(src, Promisification::promisifiedReturnValue(boundArgs), 0, propDesc) and
1141+
awaitedStep(pred, ref) and
1142+
lbl = Label::parameter(boundArgs)
1143+
)
11361144
}
11371145

11381146
/** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */
@@ -1258,19 +1266,31 @@ module API {
12581266
/** Default statue; the tracked value has not been through any steps related to promisification. */
12591267
TNotPromisified() or
12601268
/** The tracked value is a function that has been through promisification. */
1261-
TPromisifiedFunction()
1269+
TPromisifiedFunction() or
1270+
/** The tracked value is returned from a call to a promisified function, i.e. it is a promise resolving the value that eventually gets passed to a callback. */
1271+
TPromisifiedReturnValue(int callbackArgumentIndex) { callbackArgumentIndex = [0 .. 10] }
12621272

12631273
class State extends TState {
12641274
string toString() {
12651275
this = TNotPromisified() and result = "not-promisified"
12661276
or
12671277
this = TPromisifiedFunction() and result = "promisified-function"
1278+
or
1279+
exists(int i |
1280+
this = TPromisifiedReturnValue(i) and result = "promisified-return-value(" + i + ")"
1281+
)
12681282
}
12691283
}
12701284

12711285
State notPromisified() { result = TNotPromisified() }
12721286

12731287
State promisifiedFunction() { result = TPromisifiedFunction() }
1288+
1289+
State promisifiedReturnValue(int i) { result = TPromisifiedReturnValue(i) }
1290+
}
1291+
1292+
private predicate awaitedStep(DataFlow::Node node1, DataFlow::Node node2) {
1293+
StepSummary::smallstep(node1, node2, LoadStep(Promises::valueProp()))
12741294
}
12751295

12761296
/**
@@ -1305,6 +1325,16 @@ module API {
13051325
result = promisify
13061326
)
13071327
or
1328+
exists(DataFlow::CallNode call, int bound |
1329+
call =
1330+
trackUseNode(nd, Promisification::promisifiedFunction(), bound, prop, t.continue())
1331+
.getACall() and
1332+
promisified = Promisification::promisifiedReturnValue(bound + call.getNumArgument()) and
1333+
boundArgs = 0 and
1334+
result = call and
1335+
prop = ""
1336+
)
1337+
or
13081338
exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs |
13091339
trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and
13101340
prop = "" and

0 commit comments

Comments
 (0)