From b17549d4e01818303f0a883cefac0fbfcfba267a Mon Sep 17 00:00:00 2001 From: nodejs-github-bot <18269663+nodejs-github-bot@users.noreply.github.com> Date: Sun, 10 Aug 2025 00:42:35 +0000 Subject: [PATCH] deps: update zlib to 1.3.1-363a126 --- deps/zlib/BUILD.gn | 2 +- deps/zlib/README.chromium | 1 + deps/zlib/contrib/minizip/README.chromium | 1 + deps/zlib/contrib/minizip/unzip.c | 87 +++++++---- .../tests/fuzzers/minizip_unzip_fuzzer.cc | 53 +++++-- deps/zlib/contrib/tests/utils_unittest.cc | 59 +++++++ .../google/test/data/unicode_path_extra.zip | Bin 0 -> 152 bytes .../test/data/unicode_path_extra_overflow.zip | Bin 0 -> 153 bytes deps/zlib/google/test_data.filelist | 2 + ...nizip-parse-unicode-path-extra-field.patch | 145 +++++++++++++++--- src/zlib_version.h | 2 +- 11 files changed, 287 insertions(+), 65 deletions(-) create mode 100644 deps/zlib/google/test/data/unicode_path_extra.zip create mode 100644 deps/zlib/google/test/data/unicode_path_extra_overflow.zip diff --git a/deps/zlib/BUILD.gn b/deps/zlib/BUILD.gn index 9f3938021f7..3d0735452a6 100644 --- a/deps/zlib/BUILD.gn +++ b/deps/zlib/BUILD.gn @@ -419,7 +419,7 @@ static_library("minizip") { ] } - if (is_apple || is_android || is_nacl) { + if (is_apple || is_android) { # Mac, Android and the BSDs don't have fopen64, ftello64, or fseeko64. We # use fopen, ftell, and fseek instead on these systems. defines = [ "USE_FILE32API" ] diff --git a/deps/zlib/README.chromium b/deps/zlib/README.chromium index 1f7c7460451..3d2722a7e6d 100644 --- a/deps/zlib/README.chromium +++ b/deps/zlib/README.chromium @@ -3,6 +3,7 @@ Short Name: zlib URL: http://zlib.net/ Version: 1.3.1 Revision: 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf +Update Mechanism: Manual CPEPrefix: cpe:/a:zlib:zlib:1.3.1 Security Critical: yes Shipped: yes diff --git a/deps/zlib/contrib/minizip/README.chromium b/deps/zlib/contrib/minizip/README.chromium index ee70ec59ad1..0299a7e331f 100644 --- a/deps/zlib/contrib/minizip/README.chromium +++ b/deps/zlib/contrib/minizip/README.chromium @@ -3,6 +3,7 @@ Short Name: minizip URL: https://github.com/madler/zlib/tree/master/contrib/minizip Version: 1.3.1.1 Revision: ef24c4c7502169f016dcd2a26923dbaf3216748c +Update Mechanism: Manual License: Zlib License File: //third_party/zlib/LICENSE Shipped: yes diff --git a/deps/zlib/contrib/minizip/unzip.c b/deps/zlib/contrib/minizip/unzip.c index 95a945c0ac5..b77b787ccc0 100644 --- a/deps/zlib/contrib/minizip/unzip.c +++ b/deps/zlib/contrib/minizip/unzip.c @@ -64,6 +64,7 @@ */ +#include #include #include #include @@ -837,6 +838,7 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, uLong uMagic; long lSeek=0; uLong uL; + uLong uFileNameCrc; if (file==NULL) return UNZ_PARAMERROR; @@ -908,21 +910,34 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, file_info_internal.offset_curfile = uL; lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) + if (err==UNZ_OK) { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + if (file_info.size_filename > 0) + { + if (ZREAD64(s->z_filefunc, s->filestream, szCurrentFileName, file_info.size_filename) != file_info.size_filename) + { err=UNZ_ERRNO; - lSeek -= uSizeRead; + } + } + + uFileNameCrc = crc32(0, (unsigned char*)szCurrentFileName, file_info.size_filename); + + if (szFileName != NULL) + { + if (fileNameBufferSize <= file_info.size_filename) + { + memcpy(szFileName, szCurrentFileName, fileNameBufferSize); + } + else + { + memcpy(szFileName, szCurrentFileName, file_info.size_filename); + szFileName[file_info.size_filename] = '\0'; + } + } + + lSeek -= file_info.size_filename; } // Read extrafield @@ -1012,7 +1027,15 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, { int version = 0; - if (unz64local_getByte(&s->z_filefunc, s->filestream, &version) != UNZ_OK) + if (dataSize < 1 + 4) + { + /* dataSize includes version (1 byte), uCrc (4 bytes), and + * the filename data. If it's too small, fileNameSize below + * would overflow. */ + err = UNZ_ERRNO; + break; + } + else if (unz64local_getByte(&s->z_filefunc, s->filestream, &version) != UNZ_OK) { err = UNZ_ERRNO; } @@ -1025,16 +1048,16 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, } else { - uLong uCrc, uHeaderCrc, fileNameSize; + uLong uCrc, fileNameSize; if (unz64local_getLong(&s->z_filefunc, s->filestream, &uCrc) != UNZ_OK) { err = UNZ_ERRNO; } - uHeaderCrc = crc32(0, (const unsigned char *)szFileName, file_info.size_filename); - fileNameSize = dataSize - (2 * sizeof (short) + 1); + fileNameSize = dataSize - (1 + 4); /* 1 for version, 4 for uCrc */ + /* Check CRC against file name in the header. */ - if (uHeaderCrc != uCrc) + if (uCrc != uFileNameCrc) { if (ZSEEK64(s->z_filefunc, s->filestream, fileNameSize, ZLIB_FILEFUNC_SEEK_CUR) != 0) { @@ -1043,26 +1066,30 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, } else { - uLong uSizeRead; - file_info.size_filename = fileNameSize; - if (fileNameSize < fileNameBufferSize) + char szCurrentFileName[UINT16_MAX] = {0}; + + if (file_info.size_filename > 0) { - *(szFileName + fileNameSize) = '\0'; - uSizeRead = fileNameSize; - } - else - { - uSizeRead = fileNameBufferSize; - } - if ((fileNameSize > 0) && (fileNameBufferSize > 0)) - { - if (ZREAD64(s->z_filefunc, s->filestream, szFileName, uSizeRead) != uSizeRead) + if (ZREAD64(s->z_filefunc, s->filestream, szCurrentFileName, file_info.size_filename) != file_info.size_filename) { err = UNZ_ERRNO; } } + + if (szFileName != NULL) + { + if (fileNameBufferSize <= file_info.size_filename) + { + memcpy(szFileName, szCurrentFileName, fileNameBufferSize); + } + else + { + memcpy(szFileName, szCurrentFileName, file_info.size_filename); + szFileName[file_info.size_filename] = '\0'; + } + } } } } diff --git a/deps/zlib/contrib/tests/fuzzers/minizip_unzip_fuzzer.cc b/deps/zlib/contrib/tests/fuzzers/minizip_unzip_fuzzer.cc index 3b9fa446bfb..fbb779076e5 100644 --- a/deps/zlib/contrib/tests/fuzzers/minizip_unzip_fuzzer.cc +++ b/deps/zlib/contrib/tests/fuzzers/minizip_unzip_fuzzer.cc @@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include #include #include +#include #include #include "unzip.h" @@ -19,11 +21,30 @@ } while (0) extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + + unsigned long filename_sz = fdp.ConsumeIntegralInRange(0, UINT16_MAX + 3); + unsigned long extra_sz = fdp.ConsumeIntegralInRange(0, UINT16_MAX + 3); + unsigned long comment_sz = fdp.ConsumeIntegralInRange(0, UINT16_MAX + 3); + + std::unique_ptr filename; + if (fdp.ConsumeBool()) { + filename = std::make_unique(filename_sz); + } + std::unique_ptr extra; + if (fdp.ConsumeBool()) { + extra = std::make_unique(extra_sz); + } + std::unique_ptr comment; + if (fdp.ConsumeBool()) { + comment = std::make_unique(comment_sz); + } + // Mock read-only filesystem with only one file, file_data. In the calls // below, 'opaque' points to file_data, and 'strm' points to the file's seek // position, which is heap allocated so that failing to "close" it triggers a // leak error. - std::vector file_data(data, data + size); + std::vector file_data = fdp.ConsumeRemainingBytes(); zlib_filefunc64_def file_func = { .zopen64_file = [](void* opaque, const void* filename, int mode) -> void* { @@ -83,19 +104,23 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { while (true) { unz_file_info64 info = {0}; - // TODO: Pass nullptrs and different buffer sizes to cover more code. - char filename[UINT16_MAX + 1]; // +1 for the null terminator. - char extra[UINT16_MAX]; // No null terminator. - char comment[UINT16_MAX + 1]; // +1 for the null terminator. - - if (unzGetCurrentFileInfo64(uzf, &info, filename, sizeof(filename), extra, - sizeof(extra), comment, sizeof(comment)) == UNZ_OK) { - ASSERT(info.size_filename <= UINT16_MAX); - ASSERT(info.size_file_extra <= UINT16_MAX); - ASSERT(info.size_file_comment <= UINT16_MAX); - - ASSERT(filename[info.size_filename] == '\0'); - ASSERT(comment[info.size_file_comment] == '\0'); + if (unzGetCurrentFileInfo64(uzf, &info, filename.get(), filename_sz, extra.get(), + extra_sz, comment.get(), comment_sz) == UNZ_OK) { + if (filename) { + ASSERT(info.size_filename <= UINT16_MAX); + if (info.size_filename < filename_sz) { + ASSERT(filename[info.size_filename] == '\0'); + } + } + if (extra) { + ASSERT(info.size_file_extra <= UINT16_MAX); + } + if (comment) { + ASSERT(info.size_file_comment <= UINT16_MAX); + if (info.size_file_comment < comment_sz) { + ASSERT(comment[info.size_file_comment] == '\0'); + } + } } if (unzOpenCurrentFile(uzf) == UNZ_OK) { diff --git a/deps/zlib/contrib/tests/utils_unittest.cc b/deps/zlib/contrib/tests/utils_unittest.cc index f487a06996c..7d3772aa05d 100644 --- a/deps/zlib/contrib/tests/utils_unittest.cc +++ b/deps/zlib/contrib/tests/utils_unittest.cc @@ -13,6 +13,7 @@ #if !defined(CMAKE_STANDALONE_UNITTESTS) #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" +#include "base/path_service.h" #include "third_party/zlib/contrib/minizip/unzip.h" #include "third_party/zlib/contrib/minizip/zip.h" @@ -1287,4 +1288,62 @@ TEST(ZlibTest, ZipExtraFieldSize) { EXPECT_EQ(unzClose(uzf), UNZ_OK); } +static base::FilePath TestDataDir() { + base::FilePath path; + bool success = base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &path); + EXPECT_TRUE(success); + return path + .AppendASCII("third_party") + .AppendASCII("zlib") + .AppendASCII("google") + .AppendASCII("test") + .AppendASCII("data"); +} + +TEST(ZlibTest, ZipUnicodePathExtraSizeFilenameOverflow) { + // This is based on components/test/data/unzip_service/bug953599.zip (added + // in https://crrev.com/1004132), with the Unicode Path Extra Field's + // dataSize hex edited to four. + base::FilePath zip_file = TestDataDir().AppendASCII("unicode_path_extra_overflow.zip"); + unzFile uzf = unzOpen(zip_file.AsUTF8Unsafe().c_str()); + ASSERT_NE(uzf, nullptr); + EXPECT_EQ(unzGoToFirstFile(uzf), UNZ_ERRNO); + EXPECT_EQ(unzClose(uzf), UNZ_OK); +} + +TEST(ZlibTest, ZipUnicodePathExtra) { + // This is components/test/data/unzip_service/bug953599.zip (added in + // https://crrev.com/1004132). + base::FilePath zip_file = TestDataDir().AppendASCII("unicode_path_extra.zip"); + unzFile uzf = unzOpen(zip_file.AsUTF8Unsafe().c_str()); + ASSERT_NE(uzf, nullptr); + + char long_buf[15], short_buf[3]; + unz_file_info file_info; + + ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK); + ASSERT_EQ(unzGetCurrentFileInfo(uzf, &file_info, long_buf, sizeof(long_buf), + nullptr, 0, nullptr, 0), UNZ_OK); + ASSERT_EQ(file_info.size_filename, 14); + ASSERT_EQ(std::string(long_buf), "\xec\x83\x88 \xeb\xac\xb8\xec\x84\x9c.txt"); + + // Even if the file name buffer is too short to hold the whole filename, the + // unicode path extra field should get parsed correctly, size_filename set, + // and the file name buffer should receive the first bytes. + ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK); + ASSERT_EQ(unzGetCurrentFileInfo(uzf, &file_info, short_buf, sizeof(short_buf), + nullptr, 0, nullptr, 0), UNZ_OK); + ASSERT_EQ(file_info.size_filename, 14); + ASSERT_EQ(std::string(short_buf, sizeof(short_buf)), "\xec\x83\x88"); + + // Also with a null filename buffer, the unicode path extra field should get + // parsed and size_filename set correctly. + ASSERT_EQ(unzGoToFirstFile(uzf), UNZ_OK); + ASSERT_EQ(unzGetCurrentFileInfo(uzf, &file_info, nullptr, 0, nullptr, 0, + nullptr, 0), UNZ_OK); + ASSERT_EQ(file_info.size_filename, 14); + + EXPECT_EQ(unzClose(uzf), UNZ_OK); +} + #endif diff --git a/deps/zlib/google/test/data/unicode_path_extra.zip b/deps/zlib/google/test/data/unicode_path_extra.zip new file mode 100644 index 0000000000000000000000000000000000000000..bb2b1c76702bb95d57aad8e848c2b8644c145aab GIT binary patch literal 152 zcmWIWW@h1HW&nZ +Date: Thu Jul 3 17:47:55 2025 +0200 + + [minizip] Fix Unicode Path Extra Field filename length overflow + + If dataSize is too small, fileNameSize would overflow. + + Bug: 428744375 + Change-Id: I714fc1e30cb1634c31cb97ce87be225518368e57 + Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6701714 + +Author: Hans Wennborg +Date: Fri Jul 11 13:04:30 2025 +0200 + + [minizip] Fix potential OOB in unicode path extra field parsing + + The code needs to compare the CRC of the "regular" filename with the + NameCRC32 value in the unicode path extra field. However, the caller may + not have passed in a szFileName buffer large enough to hold the whole + filename, or indeed any buffer at all. + + To fix this, always read the full filename into a temporary buffer, and + compute the CRC on that. + + This also simplifies the logic for writing the filename to szFileName, + at the expense of using a small bit of extra memory, which shouldn't be + an issue for our use cases. + + Bug: 431119343 + Change-Id: Ib06e1009b6e25d2d14e36858385df46d72b7bc3e + Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6725677 + diff --git a/third_party/zlib/contrib/minizip/unzip.c b/third_party/zlib/contrib/minizip/unzip.c index c8a01b23efd42..42677cff82c96 100644 --- a/third_party/zlib/contrib/minizip/unzip.c +++ b/third_party/zlib/contrib/minizip/unzip.c +@@ -64,6 +64,7 @@ + */ + + ++#include + #include + #include + #include @@ -193,6 +193,26 @@ typedef struct Reads a long in LSB order from the given gz_stream. Sets */ @@ -66,7 +107,61 @@ index c8a01b23efd42..42677cff82c96 100644 local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX) { -@@ -948,6 +968,62 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file, +@@ -777,6 +838,7 @@ local int unz64local_GetCurrentFileInfoI + uLong uMagic; + long lSeek=0; + uLong uL; ++ uLong uFileNameCrc; + + if (file==NULL) + return UNZ_PARAMERROR; +@@ -848,21 +910,34 @@ local int unz64local_GetCurrentFileInfoI + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; +- if ((err==UNZ_OK) && (szFileName!=NULL)) ++ if (err==UNZ_OK) + { +- uLong uSizeRead ; +- if (file_info.size_filename 0) + { +- *(szFileName+file_info.size_filename)='\0'; +- uSizeRead = file_info.size_filename; ++ if (ZREAD64(s->z_filefunc, s->filestream, szCurrentFileName, file_info.size_filename) != file_info.size_filename) ++ { ++ err=UNZ_ERRNO; ++ } + } +- else +- uSizeRead = fileNameBufferSize; + +- if ((file_info.size_filename>0) && (fileNameBufferSize>0)) +- if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) +- err=UNZ_ERRNO; +- lSeek -= uSizeRead; ++ uFileNameCrc = crc32(0, (unsigned char*)szCurrentFileName, file_info.size_filename); ++ ++ if (szFileName != NULL) ++ { ++ if (fileNameBufferSize <= file_info.size_filename) ++ { ++ memcpy(szFileName, szCurrentFileName, fileNameBufferSize); ++ } ++ else ++ { ++ memcpy(szFileName, szCurrentFileName, file_info.size_filename); ++ szFileName[file_info.size_filename] = '\0'; ++ } ++ } ++ ++ lSeek -= file_info.size_filename; + } + + // Read extrafield +@@ -948,6 +1023,76 @@ local int unz64local_GetCurrentFileInfoI } } @@ -74,7 +169,15 @@ index c8a01b23efd42..42677cff82c96 100644 + { + int version = 0; + -+ if (unz64local_getByte(&s->z_filefunc, s->filestream, &version) != UNZ_OK) ++ if (dataSize < 1 + 4) ++ { ++ /* dataSize includes version (1 byte), uCrc (4 bytes), and ++ * the filename data. If it's too small, fileNameSize below ++ * would overflow. */ ++ err = UNZ_ERRNO; ++ break; ++ } ++ else if (unz64local_getByte(&s->z_filefunc, s->filestream, &version) != UNZ_OK) + { + err = UNZ_ERRNO; + } @@ -87,16 +190,16 @@ index c8a01b23efd42..42677cff82c96 100644 + } + else + { -+ uLong uCrc, uHeaderCrc, fileNameSize; ++ uLong uCrc, fileNameSize; + + if (unz64local_getLong(&s->z_filefunc, s->filestream, &uCrc) != UNZ_OK) + { + err = UNZ_ERRNO; + } -+ uHeaderCrc = crc32(0, (const unsigned char *)szFileName, file_info.size_filename); -+ fileNameSize = dataSize - (2 * sizeof (short) + 1); ++ fileNameSize = dataSize - (1 + 4); /* 1 for version, 4 for uCrc */ ++ + /* Check CRC against file name in the header. */ -+ if (uHeaderCrc != uCrc) ++ if (uCrc != uFileNameCrc) + { + if (ZSEEK64(s->z_filefunc, s->filestream, fileNameSize, ZLIB_FILEFUNC_SEEK_CUR) != 0) + { @@ -105,26 +208,30 @@ index c8a01b23efd42..42677cff82c96 100644 + } + else + { -+ uLong uSizeRead; -+ + file_info.size_filename = fileNameSize; + -+ if (fileNameSize < fileNameBufferSize) ++ char szCurrentFileName[UINT16_MAX] = {0}; ++ ++ if (file_info.size_filename > 0) + { -+ *(szFileName + fileNameSize) = '\0'; -+ uSizeRead = fileNameSize; -+ } -+ else -+ { -+ uSizeRead = fileNameBufferSize; -+ } -+ if ((fileNameSize > 0) && (fileNameBufferSize > 0)) -+ { -+ if (ZREAD64(s->z_filefunc, s->filestream, szFileName, uSizeRead) != uSizeRead) ++ if (ZREAD64(s->z_filefunc, s->filestream, szCurrentFileName, file_info.size_filename) != file_info.size_filename) + { + err = UNZ_ERRNO; + } + } ++ ++ if (szFileName != NULL) ++ { ++ if (fileNameBufferSize <= file_info.size_filename) ++ { ++ memcpy(szFileName, szCurrentFileName, fileNameBufferSize); ++ } ++ else ++ { ++ memcpy(szFileName, szCurrentFileName, file_info.size_filename); ++ szFileName[file_info.size_filename] = '\0'; ++ } ++ } + } + } + } diff --git a/src/zlib_version.h b/src/zlib_version.h index 67856b28ad6..7d14cd1bb4d 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.1-470d3a2" +#define ZLIB_VERSION "1.3.1-363a126" #endif // SRC_ZLIB_VERSION_H_