From 07320afe08b1e990d113be059337f29d1239f52d Mon Sep 17 00:00:00 2001 From: islandryu Date: Sun, 11 Jan 2026 18:46:16 +0900 Subject: [PATCH 1/2] zlib: validate write_result array length Fixes: https://github.com/nodejs/node/issues/61286 --- src/node_zlib.cc | 3 + test/parallel/test-zlib-init-assert.js | 93 ++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/parallel/test-zlib-init-assert.js diff --git a/src/node_zlib.cc b/src/node_zlib.cc index 726e7e2d4e8e85..d0077c282ba193 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -736,6 +736,7 @@ class ZlibStream final : public CompressionStream { CHECK(args[4]->IsUint32Array()); Local array = args[4].As(); + CHECK_GE(array->Length(), 2); Local ab = array->Buffer(); uint32_t* write_result = static_cast(ab->Data()); @@ -809,6 +810,7 @@ class BrotliCompressionStream final : CHECK(args.Length() == 3 && "init(params, writeResult, writeCallback)"); CHECK(args[1]->IsUint32Array()); + CHECK_GE(args[1].As()->Length(), 2); uint32_t* write_result = reinterpret_cast(Buffer::Data(args[1])); CHECK(args[2]->IsFunction()); @@ -890,6 +892,7 @@ class ZstdStream final : public CompressionStream { ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This()); CHECK(args[2]->IsUint32Array()); + CHECK_GE(args[2].As()->Length(), 2); uint32_t* write_result = reinterpret_cast(Buffer::Data(args[2])); CHECK(args[3]->IsFunction()); diff --git a/test/parallel/test-zlib-init-assert.js b/test/parallel/test-zlib-init-assert.js new file mode 100644 index 00000000000000..0c6161373faa03 --- /dev/null +++ b/test/parallel/test-zlib-init-assert.js @@ -0,0 +1,93 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const zlib = require('zlib'); +const { spawn } = require('child_process'); + +if (process.argv[2] === 'child-deflate') { + const trigger = new Uint32Array(1); + const d = zlib.createDeflate(); + d._handle.init(15, 6, 8, 0, trigger, () => {}, undefined); + d._handle.writeSync(0, Buffer.from('x'), 0, 1, Buffer.alloc(32), 0, 32); + return; +} + +if (process.argv[2] === 'child-brotli') { + const trigger = new Uint32Array(1); + const params = new Uint32Array(10).fill(-1); + const b = zlib.createBrotliCompress(); + b._handle.init(params, trigger, () => {}); + b._handle.writeSync(0, Buffer.from('x'), 0, 1, Buffer.alloc(32), 0, 32); + return; +} + +// zstd +if (process.argv[2] === 'child-zstd') { + const initParams = new Uint32Array(1); + const writeResult = new Uint32Array(1); + const zstd = zlib.createZstdCompress(); + zstd._handle.init(initParams, undefined, writeResult, () => {}); + zstd._handle.writeSync(0, Buffer.from('x'), 0, 1, Buffer.alloc(32), 0, 32); + return; +} + +{ + const child = spawn(process.execPath, [__filename, 'child-deflate'], { + stdio: ['inherit', 'inherit', 'pipe'], + }); + + let stderr = ''; + child.stderr.on('data', (data) => { + stderr += data; + }); + + child.on('close', common.mustCall((code) => { + assert.strictEqual(code, common.isWindows ? 1 : null); + const assertionMessage = 'Assertion failed: (array->Length()) >= (2)'; + assert.ok( + stderr.includes(assertionMessage), + `Expected stderr to include "${assertionMessage}", but got "${stderr}"` + ); + })); +} + +{ + const child = spawn(process.execPath, [__filename, 'child-brotli'], { + stdio: ['inherit', 'inherit', 'pipe'], + }); + + let stderr = ''; + child.stderr.on('data', (data) => { + stderr += data; + }); + + child.on('close', common.mustCall((code) => { + assert.strictEqual(code, common.isWindows ? 1 : null); + const assertionMessage = 'Assertion failed: (args[1].As()->Length()) >= (2)'; + assert.ok( + stderr.includes(assertionMessage), + `Expected stderr to include "${assertionMessage}", but got "${stderr}"` + ); + })); +} + +{ + const child = spawn(process.execPath, [__filename, 'child-zstd'], { + stdio: ['inherit', 'inherit', 'pipe'], + }); + + let stderr = ''; + child.stderr.on('data', (data) => { + stderr += data; + }); + + child.on('close', common.mustCall((code) => { + assert.strictEqual(code, common.isWindows ? 1 : null); + const assertionMessage = 'Assertion failed: (args[2].As()->Length()) >= (2)'; + assert.ok( + stderr.includes(assertionMessage), + `Expected stderr to include "${assertionMessage}", but got "${stderr}"` + ); + })); +} From 590b0bbbff5940bc5a534be161061c37d6a4fa79 Mon Sep 17 00:00:00 2001 From: islandryu Date: Mon, 12 Jan 2026 07:54:54 +0900 Subject: [PATCH 2/2] remove test --- test/parallel/test-zlib-init-assert.js | 93 -------------------------- 1 file changed, 93 deletions(-) delete mode 100644 test/parallel/test-zlib-init-assert.js diff --git a/test/parallel/test-zlib-init-assert.js b/test/parallel/test-zlib-init-assert.js deleted file mode 100644 index 0c6161373faa03..00000000000000 --- a/test/parallel/test-zlib-init-assert.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -const common = require('../common'); -const assert = require('assert'); -const zlib = require('zlib'); -const { spawn } = require('child_process'); - -if (process.argv[2] === 'child-deflate') { - const trigger = new Uint32Array(1); - const d = zlib.createDeflate(); - d._handle.init(15, 6, 8, 0, trigger, () => {}, undefined); - d._handle.writeSync(0, Buffer.from('x'), 0, 1, Buffer.alloc(32), 0, 32); - return; -} - -if (process.argv[2] === 'child-brotli') { - const trigger = new Uint32Array(1); - const params = new Uint32Array(10).fill(-1); - const b = zlib.createBrotliCompress(); - b._handle.init(params, trigger, () => {}); - b._handle.writeSync(0, Buffer.from('x'), 0, 1, Buffer.alloc(32), 0, 32); - return; -} - -// zstd -if (process.argv[2] === 'child-zstd') { - const initParams = new Uint32Array(1); - const writeResult = new Uint32Array(1); - const zstd = zlib.createZstdCompress(); - zstd._handle.init(initParams, undefined, writeResult, () => {}); - zstd._handle.writeSync(0, Buffer.from('x'), 0, 1, Buffer.alloc(32), 0, 32); - return; -} - -{ - const child = spawn(process.execPath, [__filename, 'child-deflate'], { - stdio: ['inherit', 'inherit', 'pipe'], - }); - - let stderr = ''; - child.stderr.on('data', (data) => { - stderr += data; - }); - - child.on('close', common.mustCall((code) => { - assert.strictEqual(code, common.isWindows ? 1 : null); - const assertionMessage = 'Assertion failed: (array->Length()) >= (2)'; - assert.ok( - stderr.includes(assertionMessage), - `Expected stderr to include "${assertionMessage}", but got "${stderr}"` - ); - })); -} - -{ - const child = spawn(process.execPath, [__filename, 'child-brotli'], { - stdio: ['inherit', 'inherit', 'pipe'], - }); - - let stderr = ''; - child.stderr.on('data', (data) => { - stderr += data; - }); - - child.on('close', common.mustCall((code) => { - assert.strictEqual(code, common.isWindows ? 1 : null); - const assertionMessage = 'Assertion failed: (args[1].As()->Length()) >= (2)'; - assert.ok( - stderr.includes(assertionMessage), - `Expected stderr to include "${assertionMessage}", but got "${stderr}"` - ); - })); -} - -{ - const child = spawn(process.execPath, [__filename, 'child-zstd'], { - stdio: ['inherit', 'inherit', 'pipe'], - }); - - let stderr = ''; - child.stderr.on('data', (data) => { - stderr += data; - }); - - child.on('close', common.mustCall((code) => { - assert.strictEqual(code, common.isWindows ? 1 : null); - const assertionMessage = 'Assertion failed: (args[2].As()->Length()) >= (2)'; - assert.ok( - stderr.includes(assertionMessage), - `Expected stderr to include "${assertionMessage}", but got "${stderr}"` - ); - })); -}