Skip to content

Commit e16a20e

Browse files
committed
Updated SocketClass to use API Graphs.
1 parent c7fad09 commit e16a20e

File tree

6 files changed

+60
-17
lines changed

6 files changed

+60
-17
lines changed

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

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,20 @@ private predicate areLibrariesCompatible(
4747
(client = LibraryNames::ws() or client = LibraryNames::websocket())
4848
}
4949

50+
/** Treats `WebSocket` as an entry point for API graphs. */
51+
private class WebSocketEntryPoint extends API::EntryPoint {
52+
WebSocketEntryPoint() { this = "global.WebSocket" }
53+
54+
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("WebSocket") }
55+
}
56+
57+
/** Treats `SockJS` as an entry point for API graphs. */
58+
private class SockJSEntryPoint extends API::EntryPoint {
59+
SockJSEntryPoint() { this = "global.SockJS" }
60+
61+
override DataFlow::SourceNode getASource() { result = DataFlow::globalVarRef("SockJS") }
62+
}
63+
5064
/**
5165
* Provides classes that model WebSockets clients.
5266
*/
@@ -56,19 +70,19 @@ module ClientWebSocket {
5670
/**
5771
* A class that can be used to instantiate a WebSocket instance.
5872
*/
59-
class SocketClass extends DataFlow::SourceNode {
73+
class SocketClass extends API::Node {
6074
LibraryName library; // the name of the WebSocket library. Can be one of the libraries defined in `LibraryNames`.
6175

6276
SocketClass() {
63-
this = DataFlow::globalVarRef("WebSocket") and library = websocket()
77+
this = any(WebSocketEntryPoint e).getANode() and library = websocket()
6478
or
65-
this = DataFlow::moduleImport("ws") and library = ws()
79+
this = API::moduleImport("ws") and library = ws()
6680
or
6781
// the sockjs-client library:https://www.npmjs.com/package/sockjs-client
6882
library = sockjs() and
6983
(
70-
this = DataFlow::moduleImport("sockjs-client") or
71-
this = DataFlow::globalVarRef("SockJS")
84+
this = API::moduleImport("sockjs-client") or
85+
this = any(SockJSEntryPoint e).getANode()
7286
)
7387
}
7488

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import javascript
2+
3+
API::NewNode getAWebSocketInstance() { result instanceof ClientWebSocket::ClientSocket }
4+
5+
from DataFlow::Node handler
6+
where
7+
handler = getAWebSocketInstance().getReturn().getMember("onmessage").asSource()
8+
or
9+
handler = getAWebSocketInstance().getAPropertyWrite("onmessage").getRhs()
10+
select handler, "This is a WebSocket onmessage handler."
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
import { MyWebSocket, MySockJS } from './browser.js';
22

33
(function () {
4-
const socket = new MyWebSocket('ws://localhost:9080'); // $ MISSING: clientSocket
4+
const socket = new MyWebSocket('ws://localhost:9080'); // $ clientSocket
55

66
socket.addEventListener('open', function (event) {
7-
socket.send('Hi from browser!'); // $ MISSING: clientSend
7+
socket.send('Hi from browser!'); // $ clientSend
88
});
99

1010
socket.addEventListener('message', function (event) {
1111
console.log('Message from server ', event.data);
12-
}); // $ MISSING: clientReceive
12+
}); // $ clientReceive
1313

1414
socket.onmessage = function (event) {
1515
console.log("Message from server 2", event.data)
16-
}; // $ MISSING: clientReceive
16+
}; // $ clientReceive
1717
})();
1818

1919

2020
(function () {
21-
var sock = new MySockJS('http://0.0.0.0:9999/echo'); // $ MISSING: clientSocket
21+
var sock = new MySockJS('http://0.0.0.0:9999/echo'); // $ clientSocket
2222
sock.onopen = function () {
23-
sock.send('test'); // $ MISSING: clientSend
23+
sock.send('test'); // $ clientSend
2424
};
2525

2626
sock.onmessage = function (e) {
2727
console.log('message', e.data);
2828
sock.close();
29-
}; // $ MISSING: clientReceive
29+
}; // $ clientReceive
3030

3131
sock.addEventListener('message', function (event) {
3232
console.log('Using addEventListener ', event.data);
33-
}); // $ MISSING: clientReceive
33+
}); // $ clientReceive
3434
})();
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
const { MyWebSocketWS } = require('./client.js');
22

33
(function () {
4-
const ws = new MyWebSocketWS('ws://example.org'); // $ MISSING: clientSocket
4+
const ws = new MyWebSocketWS('ws://example.org'); // $ clientSocket
55

66
ws.on('open', function open() {
7-
ws.send('Hi from client!'); // $ MISSING: clientSend
7+
ws.send('Hi from client!'); // $ clientSend
88
});
99

1010
ws.on('message', function incoming(data) {
1111
console.log(data);
12-
}); // $ MISSING: clientReceive
12+
}); // $ clientReceive
1313
})();

javascript/ql/test/library-tests/frameworks/WebSocket/server-custom.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { MyWebSocketServer } = require('./client.js');
1+
const { MyWebSocketServer } = require('./server.js');
22

33
(function () {
44
const wss = new MyWebSocketServer({ port: 8080 });

javascript/ql/test/library-tests/frameworks/WebSocket/test.expected

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,46 @@
11
clientReceive
2+
| browser-custom.js:10:37:12:2 | functio ... ta);\\n\\t} |
3+
| browser-custom.js:14:21:16:2 | functio ... ata)\\n\\t} |
4+
| browser-custom.js:26:19:29:2 | functio ... e();\\n\\t} |
5+
| browser-custom.js:31:35:33:2 | functio ... ta);\\n\\t} |
26
| browser.js:8:37:10:2 | functio ... ta);\\n\\t} |
37
| browser.js:12:21:14:2 | functio ... ata)\\n\\t} |
48
| browser.js:24:19:27:2 | functio ... e();\\n\\t} |
59
| browser.js:29:35:31:2 | functio ... ta);\\n\\t} |
10+
| client-custom.js:10:19:12:2 | functio ... ta);\\n\\t} |
611
| client.js:10:19:12:2 | functio ... ta);\\n\\t} |
712
clientSend
13+
| browser-custom.js:7:3:7:33 | socket. ... wser!') |
14+
| browser-custom.js:23:3:23:19 | sock.send('test') |
815
| browser.js:5:3:5:33 | socket. ... wser!') |
916
| browser.js:21:3:21:19 | sock.send('test') |
17+
| client-custom.js:7:3:7:28 | ws.send ... ient!') |
1018
| client.js:7:3:7:28 | ws.send ... ient!') |
1119
clientSocket
20+
| browser-custom.js:4:17:4:54 | new MyW ... :9080') |
21+
| browser-custom.js:21:13:21:52 | new MyS ... /echo') |
1222
| browser.js:2:17:2:52 | new Web ... :8080') |
1323
| browser.js:19:13:19:50 | new Soc ... /echo') |
24+
| client-custom.js:4:13:4:49 | new MyW ... e.org') |
1425
| client.js:4:13:4:45 | new Web ... e.org') |
1526
flowSteps
1627
| browser-custom.js:1:10:1:20 | MyWebSocket | browser-custom.js:1:10:1:20 | MyWebSocket |
1728
| browser-custom.js:1:23:1:30 | MySockJS | browser-custom.js:1:23:1:30 | MySockJS |
29+
| browser-custom.js:7:15:7:32 | 'Hi from browser!' | server.js:7:38:7:44 | message |
30+
| browser-custom.js:23:13:23:18 | 'test' | sockjs.js:9:31:9:37 | message |
1831
| browser.js:5:15:5:32 | 'Hi from browser!' | server.js:7:38:7:44 | message |
1932
| browser.js:21:13:21:18 | 'test' | sockjs.js:9:31:9:37 | message |
33+
| client-custom.js:7:11:7:27 | 'Hi from client!' | server.js:7:38:7:44 | message |
2034
| client.js:7:11:7:27 | 'Hi from client!' | server.js:7:38:7:44 | message |
2135
| client.js:15:32:15:44 | require('ws') | client-custom.js:1:9:1:21 | MyWebSocketWS |
36+
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:11:39:11:48 | event.data |
37+
| server.js:11:11:11:27 | 'Hi from server!' | browser-custom.js:15:40:15:49 | event.data |
2238
| server.js:11:11:11:27 | 'Hi from server!' | browser.js:9:39:9:48 | event.data |
2339
| server.js:11:11:11:27 | 'Hi from server!' | browser.js:13:40:13:49 | event.data |
40+
| server.js:11:11:11:27 | 'Hi from server!' | client-custom.js:10:37:10:40 | data |
2441
| server.js:11:11:11:27 | 'Hi from server!' | client.js:10:37:10:40 | data |
42+
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser-custom.js:27:26:27:31 | e.data |
43+
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser-custom.js:32:42:32:51 | event.data |
2544
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser.js:25:26:25:31 | e.data |
2645
| sockjs.js:11:20:11:50 | JSON.st ... .test)) | browser.js:30:42:30:51 | event.data |
2746
remoteFlow

0 commit comments

Comments
 (0)