diff --git a/deps/zlib/zlib.gyp b/deps/zlib/zlib.gyp index 12449e7b029..2cfd4ad3dc4 100644 --- a/deps/zlib/zlib.gyp +++ b/deps/zlib/zlib.gyp @@ -111,33 +111,41 @@ }], ], }, # zlib_arm_crc32 - # { - # 'target_name': 'zlib_crc32_simd', - # 'type': 'static_library', - # 'conditions': [ - # ['OS!="win" or clang==1', { - # 'cflags': [ - # '-msse4.2', - # '-mpclmul', - # ], - # 'xcode_settings': { - # 'OTHER_CFLAGS': [ - # '-msse4.2', - # '-mpclmul', - # ], - # }, - # }] - # ], - # 'defines': [ 'CRC32_SIMD_SSE42_PCLMUL' ], - # 'include_dirs': [ '<(ZLIB_ROOT)' ], - # 'direct_dependent_settings': { - # 'defines': [ 'CRC32_SIMD_SSE42_PCLMUL' ], - # 'include_dirs': [ '<(ZLIB_ROOT)' ], - # }, - # 'sources': [ - # ' target, Local unused, Local context, void* priv) { + // The bundled zlib only detects CPU features in deflateInit2() and when + // crc32() or adler32() is called with a NULL buffer. zlib.crc32() always + // passes a buffer, so trigger detection here to let it use the SIMD path + // before any stream has been created. + crc32(0, nullptr, 0); + Environment* env = Environment::GetCurrent(context); MakeClass::Make(env, target, "Zlib"); diff --git a/test/parallel/test-zlib-gzip-stored-output-boundary.js b/test/parallel/test-zlib-gzip-stored-output-boundary.js new file mode 100644 index 00000000000..44dda7e2b74 --- /dev/null +++ b/test/parallel/test-zlib-gzip-stored-output-boundary.js @@ -0,0 +1,30 @@ +'use strict'; + +// Regression test for https://github.com/nodejs/node/issues/45268. +// With gzip and level 0, deflate_stored() copies input directly into the +// output buffer through the SIMD CRC32 copy routine. An old version of that +// routine stored 16 bytes for the final (len % 16) bytes and wrote past the +// end of the output buffer, corrupting the heap. Exercise output buffers that +// end at every offset modulo 16 and check the round trip. + +require('../common'); +const assert = require('assert'); +const zlib = require('zlib'); + +for (let i = 0; i < 400; i++) { + const size = 40000 + i * 517; + const input = Buffer.alloc(size, i & 0xff); + for (let j = 0; j < size; j += 97) input[j] = j & 0xff; + const chunkSize = 65536 + (i % 17); + const gz = zlib.gzipSync(input, { level: 0, chunkSize }); + assert.deepStrictEqual(zlib.gunzipSync(gz), input); +} + +// Small inputs finished straight into a nearly full output buffer. +for (let len = 1; len <= 64; len++) { + const input = Buffer.alloc(len, 0x61); + for (let chunkSize = 64; chunkSize <= 96; chunkSize++) { + const gz = zlib.gzipSync(input, { level: 0, chunkSize }); + assert.deepStrictEqual(zlib.gunzipSync(gz), input); + } +}