From 8702b045a46956aae87b427d3e9cc5aee52dee5d Mon Sep 17 00:00:00 2001 From: XadillaX Date: Mon, 26 Apr 2021 11:54:12 +0800 Subject: [PATCH] zlib: fix brotli flush range Fixes: https://github.com/nodejs/node/issues/38407 PR-URL: https://github.com/nodejs/node/pull/38408 Reviewed-By: Anna Henningsen Reviewed-By: Zijian Liu Reviewed-By: James M Snell Reviewed-By: Rich Trott --- lib/zlib.js | 21 ++++++++++++++++++--- test/parallel/test-zlib-brotli.js | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/zlib.js b/lib/zlib.js index b192bd2e3a8be7..8242bbf7f779d0 100644 --- a/lib/zlib.js +++ b/lib/zlib.js @@ -86,7 +86,7 @@ const { BROTLI_DECODE, BROTLI_ENCODE, // Brotli operations (~flush levels) BROTLI_OPERATION_PROCESS, BROTLI_OPERATION_FLUSH, - BROTLI_OPERATION_FINISH + BROTLI_OPERATION_FINISH, BROTLI_OPERATION_EMIT_METADATA, } = constants; // Translation table for return codes. @@ -236,6 +236,13 @@ const checkRangesOrGetDefault = hideStackFrames( } ); +const FLUSH_BOUND = [ + [ Z_NO_FLUSH, Z_BLOCK ], + [ BROTLI_OPERATION_PROCESS, BROTLI_OPERATION_EMIT_METADATA ], +]; +const FLUSH_BOUND_IDX_NORMAL = 0; +const FLUSH_BOUND_IDX_BROTLI = 1; + // The base class for all Zlib-style streams. function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) { let chunkSize = Z_DEFAULT_CHUNK; @@ -245,6 +252,13 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) { assert(typeof mode === 'number'); assert(mode >= DEFLATE && mode <= BROTLI_ENCODE); + let flushBoundIdx; + if (mode !== BROTLI_ENCODE && mode !== BROTLI_DECODE) { + flushBoundIdx = FLUSH_BOUND_IDX_NORMAL; + } else { + flushBoundIdx = FLUSH_BOUND_IDX_BROTLI; + } + if (opts) { chunkSize = opts.chunkSize; if (!checkFiniteNumber(chunkSize, 'options.chunkSize')) { @@ -256,11 +270,12 @@ function ZlibBase(opts, mode, handle, { flush, finishFlush, fullFlush }) { flush = checkRangesOrGetDefault( opts.flush, 'options.flush', - Z_NO_FLUSH, Z_BLOCK, flush); + FLUSH_BOUND[flushBoundIdx][0], FLUSH_BOUND[flushBoundIdx][1], flush); finishFlush = checkRangesOrGetDefault( opts.finishFlush, 'options.finishFlush', - Z_NO_FLUSH, Z_BLOCK, finishFlush); + FLUSH_BOUND[flushBoundIdx][0], FLUSH_BOUND[flushBoundIdx][1], + finishFlush); maxOutputLength = checkRangesOrGetDefault( opts.maxOutputLength, 'options.maxOutputLength', diff --git a/test/parallel/test-zlib-brotli.js b/test/parallel/test-zlib-brotli.js index 772b655177aa18..ef31db3dd64ac4 100644 --- a/test/parallel/test-zlib-brotli.js +++ b/test/parallel/test-zlib-brotli.js @@ -71,3 +71,24 @@ const sampleBuffer = fixtures.readSync('/pss-vectors.json'); message: 'Initialization failed' }); } + +{ + // Test options.flush range + assert.throws(() => { + zlib.brotliCompressSync('', { flush: zlib.constants.Z_FINISH }); + }, { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "options.flush" is out of range. It must be >= 0 ' + + 'and <= 3. Received 4', + }); + + assert.throws(() => { + zlib.brotliCompressSync('', { finishFlush: zlib.constants.Z_FINISH }); + }, { + code: 'ERR_OUT_OF_RANGE', + name: 'RangeError', + message: 'The value of "options.finishFlush" is out of range. It must be ' + + '>= 0 and <= 3. Received 4', + }); +}