GeezerVison is showing github.com — zlib: validate pledgedSrcSize as a safe integer · nodejs/node@f322870
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/zlib.md +5-3Lines changed: 5 additions & 3 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -784,8 +784,9 @@ const stream = zlib.createZstdCompress({ | 784 | 784 | #### Pledged Source Size | 785 | 785 |
| 786 | 786 | It's possible to specify the expected total size of the uncompressed input via | 787 | | -`opts.pledgedSrcSize`. If the size doesn't match at the end of the input, | 788 | | -compression will fail with the code `ZSTD_error_srcSize_wrong`. | | 787 | +`opts.pledgedSrcSize`, which must be a non-negative safe integer. If the size | | 788 | +doesn't match at the end of the input, compression will fail with the code | | 789 | +`ZSTD_error_srcSize_wrong`. | 789 | 790 |
| 790 | 791 | #### Decompressor options | 791 | 792 |
| @@ -1927,7 +1928,8 @@ added: v25.9.0 | 1927 | 1928 | `ZSTD_btultra2`. | 1928 | 1929 | See the [Zstd compressor options][] in the zlib documentation for the | 1929 | 1930 | full list. | 1930 | | - * `pledgedSrcSize` {number} Expected uncompressed size (optional hint). | | 1931 | + * `pledgedSrcSize` {number} Expected uncompressed size as a non-negative safe | | 1932 | + integer (optional hint). | 1931 | 1933 | * `dictionary` {Buffer|TypedArray|DataView} | 1932 | 1934 | * Returns: {Object} A stateful transform. | 1933 | 1935 |
| |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/streams/iter/transform.js -10Lines changed: 0 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -257,16 +257,6 @@ function createZstdHandle(mode, options, processCallback, onError) { | 257 | 257 | validateParams(options.params, maxParam, ERR_ZSTD_INVALID_PARAM); | 258 | 258 |
| 259 | 259 | const pledgedSrcSize = options.pledgedSrcSize; | 260 | | - if (pledgedSrcSize !== undefined) { | 261 | | - if (typeof pledgedSrcSize !== 'number' || NumberIsNaN(pledgedSrcSize)) { | 262 | | - throw new ERR_INVALID_ARG_TYPE('options.pledgedSrcSize', 'number', | 263 | | - pledgedSrcSize); | 264 | | - } | 265 | | - if (pledgedSrcSize < 0) { | 266 | | - throw new ERR_OUT_OF_RANGE('options.pledgedSrcSize', '>= 0', | 267 | | - pledgedSrcSize); | 268 | | - } | 269 | | - } | 270 | 260 |
| 271 | 261 | const handle = isCompress ? | 272 | 262 | new binding.ZstdCompress() : new binding.ZstdDecompress(); | |
Collapse file Copy file name to clipboardExpand all lines: lib/zlib.js +1-1Lines changed: 1 addition & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -939,7 +939,7 @@ class Zstd extends ZlibBase { | 939 | 939 | const handle = mode === ZSTD_COMPRESS ? | 940 | 940 | new binding.ZstdCompress() : new binding.ZstdDecompress(); | 941 | 941 |
| 942 | | - const pledgedSrcSize = opts?.pledgedSrcSize ?? undefined; | | 942 | + const pledgedSrcSize = opts?.pledgedSrcSize; | 943 | 943 |
| 944 | 944 | const writeState = new Uint32Array(2); | 945 | 945 |
| |
Collapse file Copy file name to clipboardExpand all lines: src/node_zlib.cc +13-11Lines changed: 13 additions & 11 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -945,9 +945,6 @@ class ZstdStream final : public CompressionStream<CompressionContext> { | 945 | 945 | } | 946 | 946 |
| 947 | 947 | static void Init(const FunctionCallbackInfo<Value>& args) { | 948 | | - Environment* env = Environment::GetCurrent(args); | 949 | | - Local<Context> context = env->context(); | 950 | | - | 951 | 948 | CHECK((args.Length() == 4 || args.Length() == 5) && | 952 | 949 | "init(params, pledgedSrcSize, writeResult, writeCallback[, " | 953 | 950 | "dictionary])"); | @@ -964,19 +961,24 @@ class ZstdStream final : public CompressionStream<CompressionContext> { | 964 | 961 | wrap->InitStream(write_result, write_js_callback); | 965 | 962 |
| 966 | 963 | uint64_t pledged_src_size = ZSTD_CONTENTSIZE_UNKNOWN; | 967 | | - if (args[1]->IsNumber()) { | 968 | | - int64_t signed_pledged_src_size; | 969 | | - if (!args[1]->IntegerValue(context).To(&signed_pledged_src_size)) { | 970 | | - THROW_ERR_INVALID_ARG_VALUE(wrap->env(), | 971 | | - "pledgedSrcSize should be an integer"); | | 964 | + if (!args[1]->IsUndefined()) { | | 965 | + if (!args[1]->IsNumber()) { | | 966 | + THROW_ERR_INVALID_ARG_TYPE(wrap->env(), | | 967 | + "pledgedSrcSize must be a number"); | | 968 | + return; | | 969 | + } | | 970 | + if (!IsSafeJsInt(args[1])) { | | 971 | + THROW_ERR_OUT_OF_RANGE(wrap->env(), | | 972 | + "pledgedSrcSize must be a safe integer"); | 972 | 973 | return; | 973 | 974 | } | | 975 | + const int64_t signed_pledged_src_size = args[1].As<Integer>()->Value(); | 974 | 976 | if (signed_pledged_src_size < 0) { | 975 | | - THROW_ERR_INVALID_ARG_VALUE(wrap->env(), | 976 | | - "pledgedSrcSize may not be negative"); | | 977 | + THROW_ERR_OUT_OF_RANGE(wrap->env(), | | 978 | + "pledgedSrcSize must be non-negative"); | 977 | 979 | return; | 978 | 980 | } | 979 | | - pledged_src_size = signed_pledged_src_size; | | 981 | + pledged_src_size = static_cast<uint64_t>(signed_pledged_src_size); | 980 | 982 | } | 981 | 983 |
| 982 | 984 | AllocScope alloc_scope(wrap); | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-stream-iter-validation.js +10-1Lines changed: 10 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -353,7 +353,16 @@ async function testAsyncValidation() { | 353 | 353 |
| 354 | 354 | // Zstd pledgedSrcSize | 355 | 355 | await assert.rejects(consume(compressZstd({ pledgedSrcSize: 'bad' })), TYPE); | 356 | | - await assert.rejects(consume(compressZstd({ pledgedSrcSize: -1 })), RANGE); | | 356 | + for (const pledgedSrcSize of [ | | 357 | + NaN, | | 358 | + Infinity, | | 359 | + -Infinity, | | 360 | + 1.9, | | 361 | + -1, | | 362 | + Number.MAX_SAFE_INTEGER + 1, | | 363 | + ]) { | | 364 | + await assert.rejects(consume(compressZstd({ pledgedSrcSize })), RANGE); | | 365 | + } | 357 | 366 | } | 358 | 367 |
| 359 | 368 | // ============================================================================= | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-zlib-zstd-pledged-src-size.js +36Lines changed: 36 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -35,3 +35,39 @@ compressWithPledgedSrcSize({ pledgedSrcSize: 42, actualSrcSize: 0 }); | 35 | 35 | compressWithPledgedSrcSize({ pledgedSrcSize: 42, actualSrcSize: 13 }); | 36 | 36 |
| 37 | 37 | compressWithPledgedSrcSize({ pledgedSrcSize: 42, actualSrcSize: 42 }); | | 38 | + | | 39 | +function assertInvalidPledgedSrcSize(pledgedSrcSize, expected) { | | 40 | + assert.throws( | | 41 | + () => zlib.createZstdCompress({ pledgedSrcSize }), | | 42 | + expected, | | 43 | + ); | | 44 | + assert.throws( | | 45 | + () => zlib.zstdCompressSync('', { pledgedSrcSize }), | | 46 | + expected, | | 47 | + ); | | 48 | +} | | 49 | + | | 50 | +for (const pledgedSrcSize of ['1', null]) { | | 51 | + assertInvalidPledgedSrcSize(pledgedSrcSize, { | | 52 | + name: 'TypeError', | | 53 | + code: 'ERR_INVALID_ARG_TYPE', | | 54 | + }); | | 55 | +} | | 56 | + | | 57 | +for (const pledgedSrcSize of [ | | 58 | + NaN, | | 59 | + Infinity, | | 60 | + -Infinity, | | 61 | + 1.9, | | 62 | + -1, | | 63 | + Number.MAX_SAFE_INTEGER + 1, | | 64 | +]) { | | 65 | + assertInvalidPledgedSrcSize(pledgedSrcSize, { | | 66 | + name: 'RangeError', | | 67 | + code: 'ERR_OUT_OF_RANGE', | | 68 | + }); | | 69 | +} | | 70 | + | | 71 | +zlib.createZstdCompress({ | | 72 | + pledgedSrcSize: Number.MAX_SAFE_INTEGER, | | 73 | +}).destroy(); |
|