Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class TypeTracker extends TTypeTracker {

TypeTracker() { this = MkTypeTracker(hasCall, prop) }

/** Gets the summary resulting from appending `step` to this type-tracking summary. */
TypeTracker append(StepSummary step) {
step = LevelStep() and result = this
or
Expand All @@ -140,6 +141,7 @@ class TypeTracker extends TTypeTracker {
)
}

/** Gets a textual representation of this summary. */
string toString() {
exists(string withCall, string withProp |
(if hasCall = true then withCall = "with" else withCall = "without") and
Expand All @@ -153,6 +155,9 @@ class TypeTracker extends TTypeTracker {
*/
predicate start() { hasCall = false and prop = "" }

/**
* Holds if this is the end point of type tracking.
*/
predicate end() { prop = "" }

/**
Expand All @@ -162,7 +167,13 @@ class TypeTracker extends TTypeTracker {
*/
boolean hasCall() { result = hasCall }

string getProp() { result = prop }
/**
* Gets a type tracker that starts where this one has left off to allow continued
* tracking.
*
* This predicate is only defined if the type has not been tracked into a property.
*/
TypeTracker continue() { prop = "" and result = this }
}

module TypeTracker {
Expand Down Expand Up @@ -206,6 +217,7 @@ class TypeBackTracker extends TTypeBackTracker {

TypeBackTracker() { this = MkTypeBackTracker(hasReturn, prop) }

/** Gets the summary resulting from prepending `step` to this type-tracking summary. */
TypeBackTracker prepend(StepSummary step) {
step = LevelStep() and result = this
or
Expand All @@ -220,6 +232,7 @@ class TypeBackTracker extends TTypeBackTracker {
step = StoreStep(prop) and result = MkTypeBackTracker(hasReturn, "")
}

/** Gets a textual representation of this summary. */
string toString() {
exists(string withReturn, string withProp |
(if hasReturn = true then withReturn = "with" else withReturn = "without") and
Expand All @@ -233,6 +246,9 @@ class TypeBackTracker extends TTypeBackTracker {
*/
predicate start() { hasReturn = false and prop = "" }

/**
* Holds if this is the end point of type tracking.
*/
predicate end() { prop = "" }

/**
Expand All @@ -242,7 +258,13 @@ class TypeBackTracker extends TTypeBackTracker {
*/
boolean hasReturn() { result = hasReturn }

string getProp() { result = prop }
/**
* Gets a type tracker that starts where this one has left off to allow continued
* tracking.
*
* This predicate is only defined if the type has not been tracked into a property.
*/
TypeBackTracker continue() { prop = "" and result = this }
}

module TypeBackTracker {
Expand Down
10 changes: 5 additions & 5 deletions javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module SocketIO {
// exclude getter versions
exists(mcn.getAnArgument()) and
result = mcn and
t = t2
t = t2.continue()
)
)
}
Expand Down Expand Up @@ -110,7 +110,7 @@ module SocketIO {
or
// invocation of a chainable method
result = pred.getAMethodCall(namespaceChainableMethod()) and
t = t2
t = t2.continue()
or
// invocation of chainable getter method
exists(string m |
Expand All @@ -119,7 +119,7 @@ module SocketIO {
m = "volatile"
|
result = pred.getAPropertyRead(m) and
t = t2
t = t2.continue()
)
)
}
Expand Down Expand Up @@ -171,7 +171,7 @@ module SocketIO {
m = EventEmitter::chainableMethod()
|
result = pred.getAMethodCall(m) and
t = t2
t = t2.continue()
)
or
// invocation of a chainable getter method
Expand All @@ -182,7 +182,7 @@ module SocketIO {
m = "volatile"
|
result = pred.getAPropertyRead(m) and
t = t2
t = t2.continue()
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ test_ServerNode
| tst.js:15:1:15:15 | io.attach(http) | tst.js:1:12:1:33 | socket.io server |
| tst.js:16:1:16:15 | io.bind(engine) | tst.js:1:12:1:33 | socket.io server |
| tst.js:17:1:17:23 | io.onco ... socket) | tst.js:1:12:1:33 | socket.io server |
| tst.js:79:1:79:10 | obj.server | tst.js:1:12:1:33 | socket.io server |
test_ClientSendNode_getAReceiver
| client2.js:14:1:14:32 | sock.em ... there") | tst.js:72:3:72:43 | socket. ... => {}) |
| client2.js:16:1:16:36 | sock.wr ... => {}) | tst.js:70:3:70:35 | socket. ... => {}) |
Expand Down
8 changes: 8 additions & 0 deletions javascript/ql/test/library-tests/frameworks/SocketIO/tst.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,11 @@ ns.on('connection', (socket) => {
socket.once('message', (data1, data2) => {});
socket.addListener(eventName(), () => {});
});

var obj = {
server: io,
serveClient: function() { return null; }
};
obj.server; // SocketIO::ServerNode
obj.serveClient(false); // not a SocketIO::ServerNode
obj.serveClient(false).server; // not a SocketIO::ServerNode