Commit b42c0ccfa3b for nodejs
commit b42c0ccfa3bfd8800c432080a166b49c5c166206
Author: James Ross <james@jross.me>
Date: Tue Sep 29 22:48:17 2026 +0100
zlib: fix abort with decodeStrings: false
Passing decodeStrings: false to a zlib stream, or to an async
convenience method, let strings reach the native handle, which
aborts the process on its Buffer check. Force decodeStrings back to
true, as is already done for encoding and objectMode.
Signed-off-by: James Ross <james@jross.me>
PR-URL: https://github.com/nodejs/node/pull/66359
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
diff --git a/lib/zlib.js b/lib/zlib.js
index f6c5b177b58..c86fe467a23 100644
--- a/lib/zlib.js
+++ b/lib/zlib.js
@@ -302,11 +302,13 @@ class ZlibBase extends Transform {
);
}
- if (opts.encoding || opts.objectMode || opts.writableObjectMode) {
+ if (opts.encoding || opts.objectMode || opts.writableObjectMode ||
+ opts.decodeStrings === false) {
opts = { ...opts };
opts.encoding = null;
opts.objectMode = false;
opts.writableObjectMode = false;
+ opts.decodeStrings = true;
}
}
diff --git a/test/parallel/test-zlib-decode-strings.js b/test/parallel/test-zlib-decode-strings.js
new file mode 100644
index 00000000000..d5ed0e27487
--- /dev/null
+++ b/test/parallel/test-zlib-decode-strings.js
@@ -0,0 +1,32 @@
+'use strict';
+
+// Strings must be decoded before they reach the native handle, even when
+// decodeStrings: false is passed. This used to abort the process.
+
+const common = require('../common');
+const assert = require('assert');
+const zlib = require('zlib');
+
+const input = 'héllo wörld';
+
+const pairs = [
+ [zlib.createGzip, zlib.gunzipSync],
+ [zlib.createDeflate, zlib.inflateSync],
+ [zlib.createDeflateRaw, zlib.inflateRawSync],
+ [zlib.createBrotliCompress, zlib.brotliDecompressSync],
+ [zlib.createZstdCompress, zlib.zstdDecompressSync],
+];
+
+for (const [createCompress, decompressSync] of pairs) {
+ const compress = createCompress({ decodeStrings: false });
+ const chunks = [];
+ compress.on('data', (chunk) => chunks.push(chunk));
+ compress.on('end', common.mustCall(() => {
+ assert.strictEqual(decompressSync(Buffer.concat(chunks)).toString(), input);
+ }));
+ compress.end(input);
+}
+
+zlib.gzip(input, { decodeStrings: false }, common.mustSucceed((compressed) => {
+ assert.strictEqual(zlib.gunzipSync(compressed).toString(), input);
+}));