Skip to content

Commit 4688da2

Browse files
authored
Fix bug in 16-bit frame length when buffer is a subarray (#2106)
1 parent ab2e0ce commit 4688da2

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

lib/websocket/frame.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class WebsocketFrameSend {
4343
buffer[1] = payloadLength
4444

4545
if (payloadLength === 126) {
46-
new DataView(buffer.buffer).setUint16(2, bodyLength)
46+
buffer.writeUInt16BE(bodyLength, 2)
4747
} else if (payloadLength === 127) {
4848
// Clear extended payload length
4949
buffer[2] = buffer[3] = 0

test/websocket/frame.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use strict'
2+
3+
const { test } = require('tap')
4+
const { WebsocketFrameSend } = require('../../lib/websocket/frame')
5+
const { opcodes } = require('../../lib/websocket/constants')
6+
7+
test('Writing 16-bit frame length value at correct offset when buffer has a non-zero byteOffset', (t) => {
8+
/*
9+
When writing 16-bit frame lengths, a `DataView` was being used without setting a `byteOffset` into the buffer:
10+
i.e. `new DataView(buffer.buffer)` instead of `new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)`.
11+
Small `Buffers` returned by `allocUnsafe` are usually returned from the buffer pool, and thus have a non-zero `byteOffset`.
12+
Invalid frames were therefore being returned in that case.
13+
*/
14+
t.plan(3)
15+
16+
const payloadLength = 126 // 126 bytes is the smallest payload to trigger a 16-bit length field
17+
const smallBuffer = Buffer.allocUnsafe(1) // make it very likely that the next buffer returned by allocUnsafe DOESN'T have a zero byteOffset
18+
const payload = Buffer.allocUnsafe(payloadLength).fill(0)
19+
const frame = new WebsocketFrameSend(payload).createFrame(opcodes.BINARY)
20+
21+
t.equal(frame[2], payloadLength >>> 8)
22+
t.equal(frame[3], payloadLength & 0xff)
23+
t.equal(smallBuffer.length, 1) // ensure smallBuffer can't be garbage-collected too soon
24+
})

0 commit comments

Comments
 (0)