From 23d11a1dd9acac0d2f66a236c790e5debac47b25 Mon Sep 17 00:00:00 2001 From: Nitzan Uziely Date: Fri, 22 Oct 2021 20:00:45 +0300 Subject: [PATCH] dgram: fix send with out of bounds offset + length fix Socket.prototype.send sending garbage when the message is a string, or Buffer and offset+length is out of bounds. Fixes: https://github.com/nodejs/node/issues/40491 PR-URL: https://github.com/nodejs/node/pull/40568 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- lib/dgram.js | 8 ++++ .../parallel/test-dgram-send-bad-arguments.js | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/lib/dgram.js b/lib/dgram.js index c515c551427d98..57d9289853ac7a 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -40,6 +40,7 @@ const { } = require('internal/dgram'); const { guessHandleType } = internalBinding('util'); const { + ERR_BUFFER_OUT_OF_BOUNDS, ERR_INVALID_ARG_TYPE, ERR_MISSING_ARGS, ERR_SOCKET_ALREADY_BOUND, @@ -487,6 +488,13 @@ function sliceBuffer(buffer, offset, length) { offset = offset >>> 0; length = length >>> 0; + if (offset > buffer.byteLength) { + throw new ERR_BUFFER_OUT_OF_BOUNDS('offset'); + } + + if (offset + length > buffer.byteLength) { + throw new ERR_BUFFER_OUT_OF_BOUNDS('length'); + } return Buffer.from(buffer.buffer, buffer.byteOffset + offset, length); } diff --git a/test/parallel/test-dgram-send-bad-arguments.js b/test/parallel/test-dgram-send-bad-arguments.js index 3e42f31b1af4b6..b30951d441cbd2 100644 --- a/test/parallel/test-dgram-send-bad-arguments.js +++ b/test/parallel/test-dgram-send-bad-arguments.js @@ -77,6 +77,47 @@ function checkArgs(connected) { message: 'Already connected' } ); + + const longArray = [1, 2, 3, 4, 5, 6, 7, 8]; + for (const input of ['hello', + Buffer.from('hello'), + Buffer.from('hello world').subarray(0, 5), + Buffer.from('hello world').subarray(4, 9), + Buffer.from('hello world').subarray(6), + new Uint8Array([1, 2, 3, 4, 5]), + new Uint8Array(longArray).subarray(0, 5), + new Uint8Array(longArray).subarray(2, 7), + new Uint8Array(longArray).subarray(3), + new DataView(new ArrayBuffer(5), 0), + new DataView(new ArrayBuffer(6), 1), + new DataView(new ArrayBuffer(7), 1, 5)]) { + assert.throws( + () => { sock.send(input, 6, 0); }, + { + code: 'ERR_BUFFER_OUT_OF_BOUNDS', + name: 'RangeError', + message: '"offset" is outside of buffer bounds', + } + ); + + assert.throws( + () => { sock.send(input, 0, 6); }, + { + code: 'ERR_BUFFER_OUT_OF_BOUNDS', + name: 'RangeError', + message: '"length" is outside of buffer bounds', + } + ); + + assert.throws( + () => { sock.send(input, 3, 4); }, + { + code: 'ERR_BUFFER_OUT_OF_BOUNDS', + name: 'RangeError', + message: '"length" is outside of buffer bounds', + } + ); + } } else { assert.throws(() => { sock.send(buf, 1, 1, -1, host); }, RangeError); assert.throws(() => { sock.send(buf, 1, 1, 0, host); }, RangeError);