From 97718092dfedcc2f0ef33b3fff3cf5e16dd90748 Mon Sep 17 00:00:00 2001 From: "Node.js GitHub Bot" Date: Sun, 27 Sep 2026 01:01:25 +0000 Subject: [PATCH] deps: update zlib to 1.3.2.1-motley-456ae73 --- deps/zlib/BUILD.gn | 2 - .../contrib/optimizations/inffast_chunk.c | 35 +++++++++---- deps/zlib/contrib/tests/utils_unittest.cc | 50 +++++++++++++++++++ src/zlib_version.h | 2 +- 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/deps/zlib/BUILD.gn b/deps/zlib/BUILD.gn index c37b4252961e..29248e1da410 100644 --- a/deps/zlib/BUILD.gn +++ b/deps/zlib/BUILD.gn @@ -375,8 +375,6 @@ component("zlib") { # Must be after no_chromium_code for warning flags to be ordered correctly. ":zlib_warnings", ] - - allow_circular_includes_from = deps } config("minizip_warnings") { diff --git a/deps/zlib/contrib/optimizations/inffast_chunk.c b/deps/zlib/contrib/optimizations/inffast_chunk.c index 3c93da05114d..c0c7e8977d68 100644 --- a/deps/zlib/contrib/optimizations/inffast_chunk.c +++ b/deps/zlib/contrib/optimizations/inffast_chunk.c @@ -132,12 +132,14 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { } while (0) #endif +#ifdef INFLATE_CHUNK_READ_64LE + REFILL(); +#endif + /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { -#ifdef INFLATE_CHUNK_READ_64LE - REFILL(); -#else +#ifndef INFLATE_CHUNK_READ_64LE if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; @@ -145,15 +147,20 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { bits += 8; } #endif + /* Worst case: previous iteration had 3 literals (56 - 20 (lits) - 15 (lit) = 21 bits) + or a match (56 - 15 (dist) - 13 (extra) = 28 bits), leaving bits >= lenbits (<= 10). */ + Assert(bits >= state->lenbits, "inflate_fast: short lit/len index"); here = lcode + (hold & lmask); #ifdef INFLATE_CHUNK_READ_64LE - if (here->op == 0) { /* literal */ + REFILL(); + if (here->op == 0) { /* literal */ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here->val)); *out++ = (unsigned char)(here->val); hold >>= here->bits; bits -= here->bits; + Assert(bits >= state->lenbits, "inflate_fast: short 2nd lit/len index"); here = lcode + (hold & lmask); if (here->op == 0) { /* literal */ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? @@ -162,6 +169,7 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { *out++ = (unsigned char)(here->val); hold >>= here->bits; bits -= here->bits; + Assert(bits >= state->lenbits, "inflate_fast: short 3rd lit/len index"); here = lcode + (hold & lmask); } } @@ -187,6 +195,7 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { bits += 8; } #endif + Assert(bits >= op, "inflate_fast: short length extra bits"); len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; @@ -200,7 +209,14 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { bits += 8; } #endif + /* Worst case: 56 - 20 (lits) - 15 (len) - 5 (extra) = 16 bits remain for distbits <= 9. */ + Assert(bits >= state->distbits, "inflate_fast: short dist index"); here = dcode + (hold & dmask); +#ifdef INFLATE_CHUNK_READ_64LE + /* Refill after the table load so the two can overlap, and so the + distance code and its extra bits start from a full 56 bits. */ + REFILL(); +#endif dodist: op = (unsigned)(here->bits); hold >>= op; @@ -209,20 +225,17 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { if (op & 16) { /* distance base */ dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ - /* we have two fast-path loads: 10+10 + 15+5 + 15 = 55, - but we may need to refill here in the worst case */ +#ifndef INFLATE_CHUNK_READ_64LE if (bits < op) { -#ifdef INFLATE_CHUNK_READ_64LE - REFILL(); -#else hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } -#endif } +#endif + Assert(bits >= op, "inflate_fast: short distance extra bits"); dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { @@ -313,6 +326,7 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { } } else if ((op & 64) == 0) { /* 2nd level distance code */ + Assert(bits >= op, "inflate_fast: short 2nd level dist index"); here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } @@ -323,6 +337,7 @@ void ZLIB_INTERNAL inflate_fast_chunk_(z_streamp strm, unsigned start) { } } else if ((op & 64) == 0) { /* 2nd level length code */ + Assert(bits >= op, "inflate_fast: short 2nd level lit/len index"); here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } diff --git a/deps/zlib/contrib/tests/utils_unittest.cc b/deps/zlib/contrib/tests/utils_unittest.cc index 51ace780d2e7..148cc7c66558 100644 --- a/deps/zlib/contrib/tests/utils_unittest.cc +++ b/deps/zlib/contrib/tests/utils_unittest.cc @@ -1248,6 +1248,55 @@ TEST(ZlibTest, InflateCopySIGILLReproduction) { } } +TEST(ZlibTest, InflateChunkRefillDistanceBitBudget) { + // Tests the edge case where one fast-loop iteration uses 10 + 10 + 15 + 5 + + // 15 = 55 of the 56 bits a refill. There should be sufficient bits for the + // next iteration. + static const uint8_t kCompressed[] = { + 0xcd, 0xef, 0x01, 0x82, 0x24, 0x49, 0x92, 0x24, 0x49, 0x22, 0xb1, 0xa8, + 0x79, 0xf5, 0xec, 0x2f, 0x33, 0xf3, 0x17, 0xf7, 0x7a, 0xf8, 0xc6, 0x1d, + 0x20, 0xb1, 0xa8, 0x79, 0x64, 0xf5, 0xec, 0xfd, 0xf3, 0xef, 0xff, 0x1f, + 0xfc, 0xff, 0xfe, 0xfd, 0xe7, 0xdf, 0xff, 0x3f, 0xf8, 0xff, 0xfd, 0xfb, + 0xcf, 0xbf, 0xff, 0x7f, 0xf0, 0xff, 0xfb, 0x17}; + std::vector output(402 + 512); + z_stream stream = {}; + stream.next_in = const_cast(kCompressed); + stream.avail_in = sizeof(kCompressed); + stream.next_out = output.data(); + stream.avail_out = output.size(); + + ASSERT_EQ(Z_OK, inflateInit2(&stream, -MAX_WBITS)); + EXPECT_EQ(Z_STREAM_END, inflate(&stream, Z_FINISH)); + EXPECT_EQ(402u, stream.total_out); + EXPECT_EQ(Z_OK, inflateEnd(&stream)); + EXPECT_EQ('b', output[133]); // Decodes as 'a' if the refill is not reached. +} + +TEST(ZlibTest, InflateChunkRefillLiteralBitBudget) { + // Test an edge case where an iteration ends at a literal. and returns to the + // top of the inflate loop. + static const uint8_t kCompressed[] = { + 0x05, 0xe0, 0x81, 0x81, 0x04, 0x49, 0x92, 0x24, 0x49, 0xb2, 0xa8, 0x79, + 0x64, 0xcf, 0x1e, 0x96, 0x55, 0x05, 0xc5, 0x3f, 0xf4, 0x44, 0xff, 0xfe, + 0xf7, 0xcf, 0x3f, 0xff, 0xbf, 0x7f, 0xff, 0xfb, 0xe7, 0x9f, 0xff, 0xdf, + 0xbf, 0xff, 0xfd, 0xf3, 0xcf, 0xff, 0xef, 0xdf, 0xff, 0xfe, 0xf9, 0xe7, + 0xff, 0xf7, 0xef, 0x7f, 0xff, 0xfc, 0xf3, 0xff, 0xfb, 0xf7, 0xbf, 0x7f, + 0xfe, 0xf9, 0xff, 0x01}; + std::vector output(30 + 512); + z_stream stream = {}; + stream.next_in = const_cast(kCompressed); + stream.avail_in = sizeof(kCompressed); + stream.next_out = output.data(); + stream.avail_out = output.size(); + + ASSERT_EQ(Z_OK, inflateInit2(&stream, -MAX_WBITS)); + EXPECT_EQ(Z_STREAM_END, inflate(&stream, Z_FINISH)); + EXPECT_EQ(30u, stream.total_out); + EXPECT_EQ(Z_OK, inflateEnd(&stream)); + // Decodes as 'a' if the accumulator runs short before the next lookup. + EXPECT_EQ('b', output[5]); +} + // TODO(gustavoa): make these tests run standalone. #ifndef CMAKE_STANDALONE_UNITTESTS @@ -1513,3 +1562,4 @@ TEST(ZlibTest, Compare256ReachesMaxMatch) { } #endif + diff --git a/src/zlib_version.h b/src/zlib_version.h index 42c81bc0ae5d..59b9853e7ed0 100644 --- a/src/zlib_version.h +++ b/src/zlib_version.h @@ -2,5 +2,5 @@ // Refer to tools/dep_updaters/update-zlib.sh #ifndef SRC_ZLIB_VERSION_H_ #define SRC_ZLIB_VERSION_H_ -#define ZLIB_VERSION "1.3.2.1-motley-285e94b" +#define ZLIB_VERSION "1.3.2.1-motley-456ae73" #endif // SRC_ZLIB_VERSION_H_