Skip to content

Commit 2856e4b

Browse files
authored
fix(websocket): validate payload length received (nodejs#1822)
1 parent c70b9f0 commit 2856e4b

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/websocket/receiver.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,18 @@ class ByteParser extends Writable {
197197

198198
const buffer = this.consume(8)
199199
const upper = buffer.readUInt32BE(0)
200+
201+
// 2^31 is the maxinimum bytes an arraybuffer can contain
202+
// on 32-bit systems. Although, on 64-bit systems, this is
203+
// 2^53-1 bytes.
204+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length
205+
// https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275
206+
// https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e
207+
if (upper > 2 ** 31 - 1) {
208+
failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.')
209+
return
210+
}
211+
200212
const lower = buffer.readUInt32BE(4)
201213

202214
this.#info.payloadLength = (upper << 8) + lower

test/websocket/receive.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict'
2+
3+
const { test } = require('tap')
4+
const { WebSocketServer } = require('ws')
5+
const { WebSocket } = require('../..')
6+
7+
test('Receiving a frame with a payload length > 2^31-1 bytes', (t) => {
8+
t.plan(1)
9+
10+
const server = new WebSocketServer({ port: 0 })
11+
12+
server.on('connection', (ws) => {
13+
const socket = ws._socket
14+
15+
socket.write(Buffer.from([0x81, 0x7F, 0xCA, 0xE5, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00]))
16+
})
17+
18+
const ws = new WebSocket(`ws://localhost:${server.address().port}`)
19+
20+
t.teardown(() => {
21+
ws.close()
22+
server.close()
23+
})
24+
25+
ws.onmessage = t.fail
26+
27+
ws.addEventListener('error', (event) => {
28+
t.type(event.error, Error) // error event is emitted
29+
})
30+
})

0 commit comments

Comments
 (0)