Skip to content

Commit 36e02ae

Browse files
authored
Merge pull request #7912 from erik-krogh/moarApi
JS: convert more type-trackers to API-graphs
2 parents 0f60401 + 12d31d7 commit 36e02ae

File tree

7 files changed

+129
-221
lines changed

7 files changed

+129
-221
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,15 @@ import javascript
66
private import semmle.javascript.security.dataflow.Xss as Xss
77

88
module Cheerio {
9-
/**
10-
* A reference to the `cheerio` function, possibly with a loaded DOM.
11-
*/
12-
private DataFlow::SourceNode cheerioRef(DataFlow::TypeTracker t) {
13-
t.start() and
14-
(
15-
result = DataFlow::moduleImport("cheerio")
16-
or
17-
exists(string name | result = cheerioRef().getAMemberCall(name) |
18-
name = "load" or
19-
name = "parseHTML"
20-
)
21-
)
9+
/** A reference to the `cheerio` function, possibly with a loaded DOM. */
10+
private API::Node cheerioApi() {
11+
result = API::moduleImport("cheerio")
2212
or
23-
exists(DataFlow::TypeTracker t2 | result = cheerioRef(t2).track(t2, t))
13+
result = cheerioApi().getMember(["load", "parseHTML"]).getReturn()
2414
}
2515

26-
/**
27-
* A reference to the `cheerio` function, possibly with a loaded DOM.
28-
*/
29-
DataFlow::SourceNode cheerioRef() { result = cheerioRef(DataFlow::TypeTracker::end()) }
16+
/** A reference to the `cheerio` function, possibly with a loaded DOM. */
17+
DataFlow::SourceNode cheerioRef() { result = cheerioApi().getAUse() }
3018

3119
/**
3220
* A creation of `cheerio` object, a collection of virtual DOM elements
@@ -43,9 +31,9 @@ module Cheerio {
4331

4432
private class DefaultRange extends Range {
4533
DefaultRange() {
46-
this = cheerioRef().getACall()
34+
this = cheerioApi().getACall()
4735
or
48-
this = cheerioRef().getAMethodCall()
36+
this = cheerioApi().getAMember().getACall()
4937
}
5038
}
5139
}

javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -463,16 +463,11 @@ module ClientRequest {
463463
}
464464

465465
/**
466-
* Gets an instantiation `socket` of `require("net").Socket` type tracked using `t`.
466+
* Gets an instantiation `socket` of `require("net").Socket`.
467467
*/
468-
private DataFlow::SourceNode netSocketInstantiation(
469-
DataFlow::TypeTracker t, DataFlow::NewNode socket
470-
) {
471-
t.start() and
472-
socket = DataFlow::moduleMember("net", "Socket").getAnInstantiation() and
473-
result = socket
474-
or
475-
exists(DataFlow::TypeTracker t2 | result = netSocketInstantiation(t2, socket).track(t2, t))
468+
private API::Node netSocketInstantiation(DataFlow::NewNode socket) {
469+
result = API::moduleImport("net").getMember("Socket").getInstance() and
470+
socket = result.getAnImmediateUse()
476471
}
477472

478473
/**
@@ -481,9 +476,7 @@ module ClientRequest {
481476
class NetSocketRequest extends ClientRequest::Range {
482477
DataFlow::NewNode socket;
483478

484-
NetSocketRequest() {
485-
this = netSocketInstantiation(DataFlow::TypeTracker::end(), socket).getAMethodCall("connect")
486-
}
479+
NetSocketRequest() { this = netSocketInstantiation(socket).getMember("connect").getACall() }
487480

488481
override DataFlow::Node getUrl() {
489482
result = this.getArgument([0, 1]) // there are multiple overrides of `connect`, and the URL can be in the first or second argument.
@@ -495,15 +488,15 @@ module ClientRequest {
495488
responseType = "text" and
496489
promise = false and
497490
exists(DataFlow::CallNode call |
498-
call = netSocketInstantiation(DataFlow::TypeTracker::end(), socket).getAMemberCall("on") and
491+
call = netSocketInstantiation(socket).getMember("on").getACall() and
499492
call.getArgument(0).mayHaveStringValue("data") and
500493
result = call.getABoundCallbackParameter(1, 0)
501494
)
502495
}
503496

504497
override DataFlow::Node getADataNode() {
505498
exists(DataFlow::CallNode call |
506-
call = netSocketInstantiation(DataFlow::TypeTracker::end(), socket).getAMemberCall("write") and
499+
call = netSocketInstantiation(socket).getMember("write").getACall() and
507500
result = call.getArgument(0)
508501
)
509502
}
@@ -713,22 +706,15 @@ module ClientRequest {
713706
* Gets a reference to an instance of `chrome-remote-interface`.
714707
*
715708
* An instantiation of `chrome-remote-interface` either accepts a callback or returns a promise.
716-
*
717-
* The `isPromise` parameter reflects whether the reference is a promise containing
718-
* an instance of `chrome-remote-interface`, or an instance of `chrome-remote-interface`.
719709
*/
720-
private DataFlow::SourceNode chromeRemoteInterface(DataFlow::TypeTracker t) {
721-
exists(DataFlow::CallNode call |
722-
call = DataFlow::moduleImport("chrome-remote-interface").getAnInvocation()
723-
|
710+
private API::Node chromeRemoteInterface() {
711+
exists(API::CallNode call | call = API::moduleImport("chrome-remote-interface").getACall() |
724712
// the client is inside in a promise.
725-
t.startInPromise() and result = call
713+
result = call.getReturn().getPromised()
726714
or
727715
// the client is accessed directly using a callback.
728-
t.start() and result = call.getCallback([0 .. 1]).getParameter(0)
716+
result = call.getParameter([0 .. 1]).getParameter(0)
729717
)
730-
or
731-
exists(DataFlow::TypeTracker t2 | result = chromeRemoteInterface(t2).track(t2, t))
732718
}
733719

734720
/**
@@ -738,14 +724,12 @@ module ClientRequest {
738724
int optionsArg;
739725

740726
ChromeRemoteInterfaceRequest() {
741-
exists(DataFlow::SourceNode instance |
742-
instance = chromeRemoteInterface(DataFlow::TypeTracker::end())
743-
|
727+
exists(API::Node instance | instance = chromeRemoteInterface() |
744728
optionsArg = 0 and
745-
this = instance.getAPropertyRead("Page").getAMemberCall("navigate")
729+
this = instance.getMember("Page").getMember("navigate").getACall()
746730
or
747731
optionsArg = 1 and
748-
this = instance.getAMemberCall("send") and
732+
this = instance.getMember("send").getACall() and
749733
this.getArgument(0).mayHaveStringValue("Page.navigate")
750734
)
751735
}

javascript/ql/lib/semmle/javascript/frameworks/Electron.qll

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,13 @@ module Electron {
5656
}
5757
}
5858

59-
private DataFlow::SourceNode browserObject(DataFlow::TypeTracker t) {
60-
t.start() and
61-
result instanceof NewBrowserObject
62-
or
63-
exists(DataFlow::TypeTracker t2 | result = browserObject(t2).track(t2, t))
64-
}
59+
private API::Node browserObject() { result.getAnImmediateUse() instanceof NewBrowserObject }
6560

6661
/**
6762
* A data flow node whose value may originate from a browser object instantiation.
6863
*/
6964
private class BrowserObjectByFlow extends BrowserObject {
70-
BrowserObjectByFlow() { browserObject(DataFlow::TypeTracker::end()).flowsTo(this) }
65+
BrowserObjectByFlow() { browserObject().getAUse() = this }
7166
}
7267

7368
/**

0 commit comments

Comments
 (0)