From f3efce98d5eb0bbce3d4f22c1fd829732c7fb0c1 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 10 Apr 2020 12:43:15 +0200 Subject: [PATCH 1/2] 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 --- 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..f7cce71582aebc --- /dev/null +++ b/test/parallel/test-buffer-pool-untransferable.js @@ -0,0 +1,20 @@ +'use strict'; +const common = 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, port2 } = 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); From 46afefd8b0600667cf46e16a7fa2fca528ca0114 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 10 Apr 2020 12:51:49 +0200 Subject: [PATCH 2/2] fixup! buffer: mark pool ArrayBuffer as untransferable --- test/parallel/test-buffer-pool-untransferable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-buffer-pool-untransferable.js b/test/parallel/test-buffer-pool-untransferable.js index f7cce71582aebc..96e109c113fee8 100644 --- a/test/parallel/test-buffer-pool-untransferable.js +++ b/test/parallel/test-buffer-pool-untransferable.js @@ -1,5 +1,5 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const { MessageChannel } = require('worker_threads'); @@ -12,7 +12,7 @@ const b = Buffer.from('hello world'); assert.strictEqual(a.buffer, b.buffer); const length = a.length; -const { port1, port2 } = new MessageChannel(); +const { port1 } = new MessageChannel(); port1.postMessage(a, [ a.buffer ]); // Verify that the pool ArrayBuffer has not actually been transfered: