From b53193a33b7271d7a9ec6a3cf8e9eb7d210cc811 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 10 Apr 2020 12:43:15 +0200 Subject: [PATCH] buffer: mark pool ArrayBuffer as untransferable This removes a footgun in which users could attempt to transfer the pooled ArrayBuffer underlying a regular `Buffer`, which would lead to all `Buffer`s that share the same pool being rendered unusable as well, and potentially break creation of new pooled `Buffer`s. This disables this kind of transfer. Refs: https://github.com/nodejs/node/issues/32752 PR-URL: https://github.com/nodejs/node/pull/32759 Reviewed-By: Ben Noordhuis Reviewed-By: Richard Lau Reviewed-By: Colin Ihrig Reviewed-By: Gus Caplan Reviewed-By: James M Snell --- lib/buffer.js | 5 ++++- .../test-buffer-pool-untransferable.js | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-buffer-pool-untransferable.js diff --git a/lib/buffer.js b/lib/buffer.js index d83a5a30d9e1b8..cc4ee31dd581be 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -59,11 +59,13 @@ const { zeroFill: bindingZeroFill } = internalBinding('buffer'); const { + arraybuffer_untransferable_private_symbol, getOwnNonIndexProperties, propertyFilter: { ALL_PROPERTIES, ONLY_ENUMERABLE - } + }, + setHiddenValue, } = internalBinding('util'); const { customInspectSymbol, @@ -153,6 +155,7 @@ function createUnsafeBuffer(size) { function createPool() { poolSize = Buffer.poolSize; allocPool = createUnsafeBuffer(poolSize).buffer; + setHiddenValue(allocPool, arraybuffer_untransferable_private_symbol, true); poolOffset = 0; } createPool(); diff --git a/test/parallel/test-buffer-pool-untransferable.js b/test/parallel/test-buffer-pool-untransferable.js new file mode 100644 index 00000000000000..96e109c113fee8 --- /dev/null +++ b/test/parallel/test-buffer-pool-untransferable.js @@ -0,0 +1,20 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { MessageChannel } = require('worker_threads'); + +// Make sure that the pools used by the Buffer implementation are not +// transferable. +// Refs: https://github.com/nodejs/node/issues/32752 + +const a = Buffer.from('hello world'); +const b = Buffer.from('hello world'); +assert.strictEqual(a.buffer, b.buffer); +const length = a.length; + +const { port1 } = new MessageChannel(); +port1.postMessage(a, [ a.buffer ]); + +// Verify that the pool ArrayBuffer has not actually been transfered: +assert.strictEqual(a.buffer, b.buffer); +assert.strictEqual(a.length, length);