Commit 3a30bcad56a for nodejs
commit 3a30bcad56aaecc0f98afce9e702c9f44546a3f4
Author: Node.js GitHub Bot <github-bot@iojs.org>
Date: Mon Sep 28 21:40:20 2026 -0400
deps: update zlib to 1.3.2.1-motley-456ae73
PR-URL: https://github.com/nodejs/node/pull/66330
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
diff --git a/deps/zlib/BUILD.gn b/deps/zlib/BUILD.gn
index c37b4252961..29248e1da41 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 3c93da05114..c0c7e8977d6 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 51ace780d2e..148cc7c6655 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<uint8_t> output(402 + 512);
+ z_stream stream = {};
+ stream.next_in = const_cast<uint8_t*>(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<uint8_t> output(30 + 512);
+ z_stream stream = {};
+ stream.next_in = const_cast<uint8_t*>(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 42c81bc0ae5..59b9853e7ed 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_