From 6668a7a546a0b84cda4cea24f2262907dee62fea Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 14 Apr 2020 10:01:27 +0100 Subject: [PATCH 1/5] JS: Add backwards-compatible predicates to SocketIO --- .../semmle/javascript/frameworks/SocketIO.qll | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll index 45a58f9ec260..490f44fc7587 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll @@ -82,6 +82,13 @@ module SocketIO { } override DataFlow::SourceNode ref() { result = server(DataFlow::TypeTracker::end()) } + + /** + * DEPRECATED. Always returns `this` as a `ServerObject` now represents the origin of a server. + * + * Instead of `getOrigin()` to get a server origin from a reference, use `ServerObject.ref()` to get references to a given server. + */ + deprecated DataFlow::SourceNode getOrigin() { result = this } } /** A data flow node that may produce (that is, create or return) a socket.io server. */ @@ -270,6 +277,21 @@ module SocketIO { } override string getChannel() { this.getArgument(0).mayHaveStringValue(result) } + + /** Gets a parameter through which data is received from a client. */ + DataFlow::SourceNode getAReceivedItem() { result = getReceivedItem(_) } + + /** Gets a client-side node that may be sending the data received here. */ + SendNode getASender() { result.getAReceiver() = this } + + /** Gets the acknowledgment callback, if any. */ + DataFlow::FunctionNode getAck() { + result = getListener().getLastParameter() and + exists(result.getAnInvocation()) + } + + /** DEPRECATED. Use `getChannel()` instead. */ + deprecated string getEventName() { result = getChannel() } } /** An acknowledgment callback when receiving a message. */ @@ -350,6 +372,16 @@ module SocketIO { override SocketIOClient::ReceiveNode getAReceiver() { result.getSocket().getATargetNamespace() = getNamespace() } + + /** Gets the acknowledgment callback, if any. */ + DataFlow::FunctionNode getAck() { + // acknowledgments are only available when sending through a socket + exists(getSocket()) and + result = getLastArgument().getALocalSource() + } + + /** DEPRECATED. Use `getChannel()` instead. */ + deprecated string getEventName() { result = getChannel() } } /** A socket.io namespace, identified by its server and its path. */ @@ -538,6 +570,21 @@ module SocketIOClient { result != cb.getLastParameter() or not exists(result.getAnInvocation()) ) } + + /** Gets a data flow node representing data received from the server. */ + DataFlow::SourceNode getAReceivedItem() { result = getReceivedItem(_) } + + /** Gets the acknowledgment callback, if any. */ + DataFlow::FunctionNode getAck() { + result = getListener().getLastParameter() and + exists(result.getAnInvocation()) + } + + /** Gets a server-side node that may be sending the data received here. */ + SocketIO::SendNode getASender() { + result.getNamespace() = getSocket().getATargetNamespace() and + not result.getChannel() != getChannel() + } } /** An acknowledgment callback from a receive node. */ @@ -607,10 +654,23 @@ module SocketIOClient { ) } + /** Gets a data flow node representing data sent to the client. */ + DataFlow::Node getASentItem() { result = getSentItem(_) } + /** Gets a server-side node that may be receiving the data sent here. */ override SocketIO::ReceiveNode getAReceiver() { result.getSocket().getNamespace() = getSocket().getATargetNamespace() } + + /** Gets the acknowledgment callback, if any. */ + DataFlow::FunctionNode getAck() { + // acknowledgments are only available when sending through a socket + exists(getSocket()) and + result = getLastArgument().getALocalSource() + } + + /** DEPRECATED. Use `getChannel()` instead. */ + deprecated string getEventName() { result = getChannel() } } /** From 679259944fb6e411a433a02ea2285e8f273a6487 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Wed, 15 Apr 2020 10:27:32 +0100 Subject: [PATCH 2/5] JS: Address review comments --- .../semmle/javascript/frameworks/SocketIO.qll | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll index 490f44fc7587..7288b624bced 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll @@ -85,8 +85,6 @@ module SocketIO { /** * DEPRECATED. Always returns `this` as a `ServerObject` now represents the origin of a server. - * - * Instead of `getOrigin()` to get a server origin from a reference, use `ServerObject.ref()` to get references to a given server. */ deprecated DataFlow::SourceNode getOrigin() { result = this } } @@ -285,9 +283,8 @@ module SocketIO { SendNode getASender() { result.getAReceiver() = this } /** Gets the acknowledgment callback, if any. */ - DataFlow::FunctionNode getAck() { - result = getListener().getLastParameter() and - exists(result.getAnInvocation()) + DataFlow::SourceNode getAck() { + result.(ReceiveCallback).getReceiveNode() = this } /** DEPRECATED. Use `getChannel()` instead. */ @@ -311,6 +308,9 @@ module SocketIO { override SocketIOClient::SendCallback getAReceiver() { result.getSendNode().getAReceiver() = rcv } + + /** Gets the API call to which this is a callback. */ + ReceiveNode getReceiveNode() { result = rcv } } /** @@ -575,7 +575,7 @@ module SocketIOClient { DataFlow::SourceNode getAReceivedItem() { result = getReceivedItem(_) } /** Gets the acknowledgment callback, if any. */ - DataFlow::FunctionNode getAck() { + DataFlow::SourceNode getAck() { result = getListener().getLastParameter() and exists(result.getAnInvocation()) } @@ -588,11 +588,11 @@ module SocketIOClient { } /** An acknowledgment callback from a receive node. */ - class RecieveCallback extends EventDispatch::Range, DataFlow::SourceNode { + class ReceiveCallback extends EventDispatch::Range, DataFlow::SourceNode { override SocketObject emitter; ReceiveNode rcv; - RecieveCallback() { + ReceiveCallback() { this = rcv.getListener().getLastParameter() and exists(this.getAnInvocation()) and emitter = rcv.getEmitter() From d4978905f8fb38dd72d94c861eefb86a5a63fd84 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 20 Apr 2020 15:12:04 +0100 Subject: [PATCH 3/5] JS: Use SendCallback/ReceiveCallback in getAck --- .../semmle/javascript/frameworks/SocketIO.qll | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll index 7288b624bced..8ccd8546c8a5 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll @@ -283,8 +283,8 @@ module SocketIO { SendNode getASender() { result.getAReceiver() = this } /** Gets the acknowledgment callback, if any. */ - DataFlow::SourceNode getAck() { - result.(ReceiveCallback).getReceiveNode() = this + ReceiveCallback getAck() { + result.getReceiveNode() = this } /** DEPRECATED. Use `getChannel()` instead. */ @@ -374,10 +374,8 @@ module SocketIO { } /** Gets the acknowledgment callback, if any. */ - DataFlow::FunctionNode getAck() { - // acknowledgments are only available when sending through a socket - exists(getSocket()) and - result = getLastArgument().getALocalSource() + SendCallback getAck() { + result.getSendNode() =this } /** DEPRECATED. Use `getChannel()` instead. */ @@ -576,8 +574,7 @@ module SocketIOClient { /** Gets the acknowledgment callback, if any. */ DataFlow::SourceNode getAck() { - result = getListener().getLastParameter() and - exists(result.getAnInvocation()) + result.(ReceiveCallback).getReceiveNode() = this } /** Gets a server-side node that may be sending the data received here. */ @@ -664,9 +661,7 @@ module SocketIOClient { /** Gets the acknowledgment callback, if any. */ DataFlow::FunctionNode getAck() { - // acknowledgments are only available when sending through a socket - exists(getSocket()) and - result = getLastArgument().getALocalSource() + result.(SendCallback).getSendNode() = this } /** DEPRECATED. Use `getChannel()` instead. */ From 4fc79e38ec926d55f6a2888bb958e6b82b19acbd Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Mon, 20 Apr 2020 15:24:51 +0100 Subject: [PATCH 4/5] JS: Also fix typo in test case --- .../frameworks/SocketIO/ClientReceiveNode_getAck.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/test/library-tests/frameworks/SocketIO/ClientReceiveNode_getAck.qll b/javascript/ql/test/library-tests/frameworks/SocketIO/ClientReceiveNode_getAck.qll index e74315833304..4d32fc78059d 100644 --- a/javascript/ql/test/library-tests/frameworks/SocketIO/ClientReceiveNode_getAck.qll +++ b/javascript/ql/test/library-tests/frameworks/SocketIO/ClientReceiveNode_getAck.qll @@ -1,7 +1,7 @@ import javascript query predicate test_ClientReceiveNode_getAck( - SocketIOClient::ReceiveNode rn, SocketIOClient::RecieveCallback res + SocketIOClient::ReceiveNode rn, SocketIOClient::ReceiveCallback res ) { res.getReceiveNode() = rn } From 997b44928e935d13109d4faf79dd375dca43c050 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 21 Apr 2020 10:14:28 +0100 Subject: [PATCH 5/5] JS: Autoformat --- .../semmle/javascript/frameworks/SocketIO.qll | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll index 8ccd8546c8a5..9f5cdf2f1c7a 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll @@ -283,9 +283,7 @@ module SocketIO { SendNode getASender() { result.getAReceiver() = this } /** Gets the acknowledgment callback, if any. */ - ReceiveCallback getAck() { - result.getReceiveNode() = this - } + ReceiveCallback getAck() { result.getReceiveNode() = this } /** DEPRECATED. Use `getChannel()` instead. */ deprecated string getEventName() { result = getChannel() } @@ -374,9 +372,7 @@ module SocketIO { } /** Gets the acknowledgment callback, if any. */ - SendCallback getAck() { - result.getSendNode() =this - } + SendCallback getAck() { result.getSendNode() = this } /** DEPRECATED. Use `getChannel()` instead. */ deprecated string getEventName() { result = getChannel() } @@ -573,9 +569,7 @@ module SocketIOClient { DataFlow::SourceNode getAReceivedItem() { result = getReceivedItem(_) } /** Gets the acknowledgment callback, if any. */ - DataFlow::SourceNode getAck() { - result.(ReceiveCallback).getReceiveNode() = this - } + DataFlow::SourceNode getAck() { result.(ReceiveCallback).getReceiveNode() = this } /** Gets a server-side node that may be sending the data received here. */ SocketIO::SendNode getASender() { @@ -660,9 +654,7 @@ module SocketIOClient { } /** Gets the acknowledgment callback, if any. */ - DataFlow::FunctionNode getAck() { - result.(SendCallback).getSendNode() = this - } + DataFlow::FunctionNode getAck() { result.(SendCallback).getSendNode() = this } /** DEPRECATED. Use `getChannel()` instead. */ deprecated string getEventName() { result = getChannel() }