deps: update zlib to 1.3.1-470d3a2

PR-URL: https://github.com/nodejs/node/pull/58628
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
Node.js GitHub Bot 2025-06-09 21:07:34 -04:00 committed by GitHub
parent bce60abdb1
commit a45f1ad8ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
44 changed files with 890 additions and 324 deletions

18
deps/zlib/BUILD.gn vendored
View File

@ -173,12 +173,15 @@ if (use_arm_neon_optimizations) {
}
}
config("zlib_inflate_chunk_simd_config") {
config("zlib_data_chunk_simd_config") {
if (use_x86_x64_optimizations) {
defines = [ "INFLATE_CHUNK_SIMD_SSE2" ]
if (current_cpu == "x64") {
defines += [ "INFLATE_CHUNK_READ_64LE" ]
defines += [
"INFLATE_CHUNK_READ_64LE",
"DEFLATE_CHUNK_WRITE_64LE",
]
}
}
@ -186,12 +189,15 @@ config("zlib_inflate_chunk_simd_config") {
defines = [ "INFLATE_CHUNK_SIMD_NEON" ]
if (current_cpu == "arm64") {
defines += [ "INFLATE_CHUNK_READ_64LE" ]
defines += [
"INFLATE_CHUNK_READ_64LE",
"DEFLATE_CHUNK_WRITE_64LE",
]
}
}
}
source_set("zlib_inflate_chunk_simd") {
source_set("zlib_data_chunk_simd") {
visibility = [ ":*" ]
if (use_x86_x64_optimizations || use_arm_neon_optimizations) {
@ -213,7 +219,7 @@ source_set("zlib_inflate_chunk_simd") {
configs += [ "//build/config/compiler:no_chromium_code" ]
configs += [ ":zlib_warnings" ]
public_configs = [ ":zlib_inflate_chunk_simd_config" ]
public_configs = [ ":zlib_data_chunk_simd_config" ]
public_deps = [ ":zlib_common_headers" ]
}
@ -336,7 +342,7 @@ component("zlib") {
if (use_x86_x64_optimizations || use_arm_neon_optimizations) {
deps += [
":zlib_adler32_simd",
":zlib_inflate_chunk_simd",
":zlib_data_chunk_simd",
":zlib_slide_hash_simd",
]

View File

@ -3,7 +3,7 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
project(zlib C)
set(VERSION "1.3.0.1")
set(VERSION "1.3.1")
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
@ -47,6 +47,7 @@ if (ENABLE_SIMD_OPTIMIZATIONS)
add_definitions(-DINFLATE_CHUNK_SIMD_SSE2)
add_definitions(-DADLER32_SIMD_SSSE3)
add_definitions(-DINFLATE_CHUNK_READ_64LE)
add_definitions(-DDEFLATE_CHUNK_WRITE_64LE)
add_definitions(-DCRC32_SIMD_SSE42_PCLMUL)
if (ENABLE_SIMD_AVX512)
add_definitions(-DCRC32_SIMD_AVX512_PCLMUL)
@ -64,6 +65,7 @@ if (ENABLE_SIMD_OPTIMIZATIONS)
add_definitions(-DINFLATE_CHUNK_SIMD_NEON)
add_definitions(-DADLER32_SIMD_NEON)
add_definitions(-DINFLATE_CHUNK_READ_64LE)
add_definitions(-DDEFLATE_CHUNK_WRITE_64LE)
add_definitions(-DCRC32_ARMV8_CRC32)
add_definitions(-DDEFLATE_SLIDE_HASH_NEON)
# Required by CPU features detection code.
@ -83,10 +85,13 @@ if (ENABLE_SIMD_OPTIMIZATIONS)
add_definitions(-DDEFLATE_SLIDE_HASH_RVV)
add_definitions(-DADLER32_SIMD_RVV)
# TODO(cavalcantii): add remaining flags as we port optimizations to RVV.
# chunk_copy is required for READ64 and unconditional decode of literals.
add_definitions(-DINFLATE_CHUNK_GENERIC)
add_definitions(-DINFLATE_CHUNK_READ_64LE)
add_definitions(-DDEFLATE_CHUNK_WRITE_64LE)
# TODO(cavalcantii): only missing optimization is SLIDE_HASH, got port it
# to RISCV.
# Tested with clang-17, unaligned loads are required by read64 & chunk_copy.
# TODO(cavalcantii): replace internal clang flags for -munaligned-access
@ -267,7 +272,9 @@ if(MINGW)
endif(MINGW)
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
set_target_properties(zlib PROPERTIES SOVERSION 1)

5
deps/zlib/OWNERS vendored
View File

@ -1,4 +1,3 @@
agl@chromium.org
cavalcantii@chromium.org
cblume@chromium.org
scroggo@google.com
hans@chromium.org
agl@chromium.org #{LAST_RESORT_SUGGESTION}

View File

@ -1,9 +1,9 @@
Name: zlib
Short Name: zlib
URL: http://zlib.net/
Version: 1.3.0.1
Revision: ac8f12c97d1afd9bafa9c710f827d40a407d3266
CPEPrefix: cpe:/a:zlib:zlib:1.3.0.1
Version: 1.3.1
Revision: 51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf
CPEPrefix: cpe:/a:zlib:zlib:1.3.1
Security Critical: yes
Shipped: yes
License: Zlib
@ -21,14 +21,17 @@ also implements the zlib (RFC 1950) and gzip (RFC 1952) wrapper formats.
Local Modifications:
- Only source code from the zlib distribution used to build the zlib and
minizip libraries are present. Many other files have been omitted. Only *.c
and *.h files from the upstream root directory and contrib/minizip were
imported.
and *.h files from the upstream root directory, contrib/minizip and
examples/zpipe.c were imported.
- The files named '*simd*' are original x86/Arm/RISC-V specific optimizations.
- The contents of the google directory are original Chromium-specific
additions.
- The contents of the 'contrib' of directory are either Chromium-specific
additions or heavily patched zlib files (e.g. inffast_chunk*).
- Added chromeconf.h
- Plus the changes in 'patches' folder.
- Code in contrib/ other than contrib/minizip was added to match zlib's
contributor layout.
- In sync with 1.2.13 official release
- In sync with 1.3.1 official release
- ZIP reader modified to allow for progress callbacks during extraction.
- ZIP reader modified to add detection of AES encrypted content.

View File

@ -34,3 +34,8 @@ Local Modifications:
https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT section 4.6.9.
(see crrev.com/1002476)
0016-minizip-parse-unicode-path-extra-field.patch
- Added support for zip64 archives that have extra bytes on front (for example,
large CRX files).
0018-support-prefixed-zip64.patch

View File

@ -482,6 +482,46 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (uL != 1)
return CENTRALDIRINVALID;
/* If bytes are pre-pended to the archive, relativeOffset must be advanced
by that many bytes. The central dir must exist between the specified
relativeOffset and uPosFound. */
if (relativeOffset > uPosFound)
return CENTRALDIRINVALID;
const int BUFSIZE = 1024 * 4;
buf = (unsigned char*)ALLOC(BUFSIZE);
if (buf==NULL)
return CENTRALDIRINVALID;
// Zip64 EOCDR is at least 48 bytes long.
while (uPosFound - relativeOffset >= 48) {
int found = 0;
uLong uReadSize = uPosFound - relativeOffset;
if (uReadSize > BUFSIZE) {
uReadSize = BUFSIZE;
}
if (ZSEEK64(*pzlib_filefunc_def, filestream, relativeOffset, ZLIB_FILEFUNC_SEEK_SET) != 0) {
break;
}
if (ZREAD64(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize) {
break;
}
for (int i = 0; i < uReadSize - 3; ++i) {
// Looking for 0x06064b50, the Zip64 EOCDR signature.
if (buf[i] == 0x50 && buf[i + 1] == 0x4b &&
buf[i + 2] == 0x06 && buf[i + 3] == 0x06)
{
relativeOffset += i;
found = 1;
break;
}
}
if (found) {
break;
}
// Re-read the last 3 bytes, in case they're the front of the signature.
relativeOffset += uReadSize - 3;
}
free(buf);
/* Goto end of central directory record */
if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
return CENTRALDIRINVALID;
@ -1005,6 +1045,8 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file,
{
uLong uSizeRead;
file_info.size_filename = fileNameSize;
if (fileNameSize < fileNameBufferSize)
{
*(szFileName + fileNameSize) = '\0';

View File

@ -43,3 +43,9 @@ fuzzer_test("zlib_deflate_fuzzer") {
sources = [ "deflate_fuzzer.cc" ]
deps = [ "../../../:zlib" ]
}
fuzzer_test("minizip_unzip_fuzzer") {
sources = [ "minizip_unzip_fuzzer.cc" ]
deps = [ "../../../:minizip" ]
include_dirs = [ "//third_party/zlib/contrib/minizip" ]
}

View File

@ -0,0 +1,119 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <vector>
#include "unzip.h"
// Fuzzer builds often have NDEBUG set, so roll our own assert macro.
#define ASSERT(cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "%s:%d Assert failed: %s\n", __FILE__, __LINE__, #cond); \
exit(1); \
} \
} while (0)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// 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<uint8_t> file_data(data, data + size);
zlib_filefunc64_def file_func = {
.zopen64_file = [](void* opaque, const void* filename,
int mode) -> void* {
ASSERT(mode == (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING));
return new size_t(0);
},
.zread_file = [](void* opaque, void* strm, void* buf,
uLong size) -> uLong {
std::vector<uint8_t>* vec = static_cast<std::vector<uint8_t>*>(opaque);
size_t* pos = static_cast<size_t*>(strm);
if (*pos >= vec->size()) {
return 0;
}
size = std::min(static_cast<size_t>(size), vec->size() - *pos);
memcpy(buf, vec->data() + *pos, size);
(*pos) += size;
return size;
},
.zwrite_file = [](void*, void*, const void*, uLong) -> uLong {
ASSERT(0 && "Writing is not supported.");
return 0;
},
.ztell64_file = [](void*, void* strm) -> ZPOS64_T {
return *static_cast<size_t*>(strm);
},
.zseek64_file = [](void* opaque, void* strm, ZPOS64_T offset,
int origin) -> long {
std::vector<uint8_t>* vec = static_cast<std::vector<uint8_t>*>(opaque);
size_t* pos = static_cast<size_t*>(strm);
switch (origin) {
case ZLIB_FILEFUNC_SEEK_SET:
*pos = offset;
break;
case ZLIB_FILEFUNC_SEEK_CUR:
*pos = *pos + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
*pos = vec->size() + offset;
break;
default:
ASSERT(0 && "Invalid origin");
}
return 0;
},
.zclose_file = [](void*, void* strm) -> int {
delete static_cast<size_t*>(strm);
return 0;
},
.zerror_file = [](void*, void*) -> int { return 0; },
.opaque = &file_data};
unzFile uzf = unzOpen2_64("foo.zip", &file_func);
if (uzf == NULL) {
return 0;
}
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 (unzOpenCurrentFile(uzf) == UNZ_OK) {
while (true) {
char buffer[4096];
int num_read = unzReadCurrentFile(uzf, buffer, sizeof(buffer));
if (num_read <= 0) {
break;
}
}
unzCloseCurrentFile(uzf);
}
if (unzGoToNextFile(uzf) != UNZ_OK) {
break;
}
}
unzClose(uzf);
return 0;
}

36
deps/zlib/deflate.c vendored
View File

@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -69,7 +69,7 @@
#endif
const char deflate_copyright[] =
" deflate 1.3.0.1 Copyright 1995-2023 Jean-loup Gailly and Mark Adler ";
" deflate 1.3.1 Copyright 1995-2024 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@ -790,7 +790,11 @@ int ZEXPORT deflatePrime(z_streamp strm, int bits, int value) {
put = Buf_size - s->bi_valid;
if (put > bits)
put = bits;
#if defined(DEFLATE_CHUNK_WRITE_64LE)
s->bi_buf |= (uint64_t)((value & ((1ULL << put) - 1)) << s->bi_valid);
#else
s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid);
#endif /* DEFLATE_CHUNK_WRITE_64LE */
s->bi_valid += put;
_tr_flush_bits(s);
value >>= put;
@ -1663,13 +1667,21 @@ local uInt longest_match(deflate_state *s, IPos cur_match) {
*/
local void check_match(deflate_state *s, IPos start, IPos match, int length) {
/* check that the match is indeed a match */
if (zmemcmp(s->window + match,
s->window + start, length) != EQUAL) {
fprintf(stderr, " start %u, match %u, length %d\n",
start, match, length);
Bytef *back = s->window + (int)match, *here = s->window + start;
IPos len = length;
if (match == (IPos)-1) {
/* match starts one byte before the current window -- just compare the
subsequent length-1 bytes */
back++;
here++;
len--;
}
if (zmemcmp(back, here, len) != EQUAL) {
fprintf(stderr, " start %u, match %d, length %d\n",
start, (int)match, length);
do {
fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
} while (--length != 0);
fprintf(stderr, "(%02x %02x)", *back++, *here++);
} while (--len != 0);
z_error("invalid match");
}
if (z_verbose > 1) {
@ -2106,13 +2118,7 @@ local block_state deflate_slow(deflate_state *s, int flush) {
uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
/* Do not insert strings in hash table beyond this. */
if (s->prev_match == -1) {
/* The window has slid one byte past the previous match,
* so the first byte cannot be compared. */
check_match(s, s->strstart, s->prev_match + 1, s->prev_length - 1);
} else {
check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
}
check_match(s, s->strstart - 1, s->prev_match, s->prev_length);
_tr_tally_dist(s, s->strstart - 1 - s->prev_match,
s->prev_length - MIN_MATCH, bflush);

14
deps/zlib/deflate.h vendored
View File

@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
* Copyright (C) 1995-2018 Jean-loup Gailly
* Copyright (C) 1995-2024 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -13,6 +13,10 @@
#ifndef DEFLATE_H
#define DEFLATE_H
#if defined(DEFLATE_CHUNK_WRITE_64LE)
#include <stdint.h>
#endif
#include "zutil.h"
/* define NO_GZIP when compiling if you want to disable gzip header and
@ -52,7 +56,11 @@
#define MAX_BITS 15
/* All codes must not exceed MAX_BITS bits */
#if defined(DEFLATE_CHUNK_WRITE_64LE)
#define Buf_size 64
#else
#define Buf_size 16
#endif
/* size of bit buffer in bi_buf */
#define INIT_STATE 42 /* zlib header -> BUSY_STATE */
@ -261,7 +269,11 @@ typedef struct internal_state {
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
#endif
#if defined(DEFLATE_CHUNK_WRITE_64LE)
uint64_t bi_buf;
#else
ush bi_buf;
#endif
/* Output buffer. bits are inserted starting at the bottom (least
* significant bits).
*/

View File

@ -2,5 +2,4 @@ satorux@chromium.org
# compression_utils*
asvitkine@chromium.org
isherman@chromium.org
cavalcantii@chromium.org

View File

@ -0,0 +1,48 @@
# Creates zip files for symlink-related tests.
import zipfile
def make_zip(filename):
return zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
def make_link(zf, target, link):
zip_info = zipfile.ZipInfo(link)
zip_info.external_attr = 0o120777 << 16 # lrwxrwxrwx
zf.writestr(zip_info, target)
def make_file(zf, path, content):
zf.writestr(zipfile.ZipInfo(path), content)
def make_test_zips():
with make_zip('symlinks.zip') as zf:
make_file(zf, 'a.txt', 'A')
make_file(zf, 'b.txt', 'B')
make_file(zf, 'dir/c.txt', 'C')
make_link(zf, '../a.txt', 'dir/a_link')
make_link(zf, 'b.txt', 'b_link')
make_link(zf, 'dir/c.txt', 'c_link')
with make_zip('symlink_evil_relative_path.zip') as zf:
make_file(zf, 'dir/a.txt', 'A')
make_link(zf, 'dir/../dir/../../outside.txt', 'evil_link')
with make_zip('symlink_absolute_path.zip') as zf:
make_link(zf, '/absolute/path/to/outside.txt', 'absolute_link')
with make_zip('symlink_too_large.zip') as zf:
make_link(zf, 'a' * 10000, 'big_link')
with make_zip('symlink_follow_own_link.zip') as zf:
make_link(zf, 'file', 'link')
make_file(zf, 'link', 'Hello world')
with make_zip('symlink_duplicate_link.zip') as zf:
make_link(zf, 'target_1', 'link')
make_link(zf, 'target_2', 'link')
if __name__ == '__main__':
make_test_zips()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
deps/zlib/google/test/data/symlinks.zip vendored Normal file

Binary file not shown.

View File

@ -15,11 +15,18 @@ test/data/Repeated File Name.zip
test/data/SJIS Bug 846195.zip
test/data/Windows Special Names.zip
test/data/Wrong CRC.zip
test/data/create_symlink_test_zips.py
test/data/create_test_zip.sh
test/data/empty.zip
test/data/evil.zip
test/data/evil_via_absolute_file_name.zip
test/data/evil_via_invalid_utf8.zip
test/data/symlink_absolute_path.zip
test/data/symlink_duplicate_link.zip
test/data/symlink_evil_relative_path.zip
test/data/symlink_follow_own_link.zip
test/data/symlink_too_large.zip
test/data/symlinks.zip
test/data/test.zip
test/data/test/foo.txt
test/data/test/foo/bar.txt

View File

@ -4,13 +4,16 @@
#include "third_party/zlib/google/zip.h"
#include <cstdint>
#include <string>
#include <vector>
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
@ -23,6 +26,11 @@
namespace zip {
namespace {
#if defined(OS_POSIX)
// The maximum allowed size of a symbolic link in bytes.
constexpr uint64_t kMaxSymlinkFileSize = 8192;
#endif
bool IsHiddenFile(const base::FilePath& file_path) {
return file_path.BaseName().value()[0] == '.';
}
@ -36,6 +44,34 @@ bool CreateDirectory(const base::FilePath& extract_dir,
return ok;
}
#if defined(OS_POSIX)
// Creates a symbolic link at |extract_dir|/|target| to |link|. Fails if |link|
// points outside of |extract_dir|.
bool CreateSymbolicLink(const base::FilePath& extract_dir,
const base::FilePath& target,
const base::FilePath& link) {
const base::FilePath full_link_path = extract_dir.Append(link);
if (target.IsAbsolute()) {
LOG(ERROR) << "Won't create link with an absolute target "
<< Redact(target);
return false;
}
std::optional<base::FilePath> absolute_target =
base::MakeAbsoluteFilePathNoResolveSymbolicLinks(
full_link_path.DirName().Append(target));
if (!absolute_target) {
LOG(ERROR) << "Failed to make an absolute path to " << Redact(target);
return false;
}
if (!extract_dir.IsParent(*absolute_target)) {
LOG(ERROR) << "Won't create link with target outside extract dir "
<< Redact(target);
return false;
}
return base::CreateSymbolicLink(target, full_link_path);
}
#endif // defined(OS_POSIX)
// Creates a WriterDelegate that can write a file at |extract_dir|/|entry_path|.
std::unique_ptr<WriterDelegate> CreateFilePathWriterDelegate(
const base::FilePath& extract_dir,
@ -113,6 +149,95 @@ class DirectFileAccessor : public FileAccessor {
const base::FilePath src_dir_;
};
// |symlink_creator| may be null in which case symbolic link entries are
// considered errors.
bool UnzipImpl(
const base::PlatformFile& src_file,
WriterFactory writer_factory,
DirectoryCreator directory_creator,
UnzipOptions options,
base::RepeatingCallback<bool(const base::FilePath&, const base::FilePath&)>
symlink_creator) {
ZipReader reader;
reader.SetEncoding(std::move(options.encoding));
reader.SetPassword(std::move(options.password));
if (!reader.OpenFromPlatformFile(src_file)) {
LOG(ERROR) << "Cannot open ZIP from file handle " << src_file;
return false;
}
while (const ZipReader::Entry* const entry = reader.Next()) {
if (entry->is_unsafe) {
LOG(ERROR) << "Found unsafe entry " << Redact(entry->path) << " in ZIP";
if (!options.continue_on_error) {
return false;
}
continue;
}
if (options.filter && !options.filter.Run(entry->path)) {
VLOG(1) << "Skipped ZIP entry " << Redact(entry->path);
continue;
}
if (entry->is_directory) {
// It's a directory.
if (!directory_creator.Run(entry->path)) {
LOG(ERROR) << "Cannot create directory " << Redact(entry->path);
if (!options.continue_on_error) {
return false;
}
}
continue;
}
#if defined(OS_POSIX)
if (entry->is_symbolic_link) {
if (!symlink_creator) {
LOG(ERROR) << "Skipping symbolic link " << Redact(entry->path);
if (!options.continue_on_error) {
return false;
}
continue;
}
std::string target;
if (!reader.ExtractCurrentEntryToString(kMaxSymlinkFileSize, &target)) {
LOG(ERROR) << "Failed to read link target " << Redact(entry->path);
if (!options.continue_on_error) {
return false;
}
continue;
}
if (!symlink_creator.Run(base::FilePath(target), entry->path)) {
LOG(ERROR) << "Failed to create symbolic link " << Redact(entry->path);
if (!options.continue_on_error) {
return false;
}
continue;
}
continue;
}
#endif // defined(OS_POSIX)
// It's a file.
std::unique_ptr<WriterDelegate> writer = writer_factory.Run(entry->path);
if (!writer ||
(options.progress ? !reader.ExtractCurrentEntryWithListener(
writer.get(), options.progress)
: !reader.ExtractCurrentEntry(writer.get()))) {
LOG(ERROR) << "Cannot extract file " << Redact(entry->path)
<< " from ZIP";
if (!options.continue_on_error) {
return false;
}
}
}
return reader.ok();
}
} // namespace
std::ostream& operator<<(std::ostream& out, const Progress& progress) {
@ -132,15 +257,17 @@ bool Zip(const ZipParams& params) {
DCHECK(params.dest_file.empty());
zip_writer =
internal::ZipWriter::CreateWithFd(params.dest_fd, file_accessor);
if (!zip_writer)
if (!zip_writer) {
return false;
}
}
#endif
if (!zip_writer) {
zip_writer = internal::ZipWriter::Create(params.dest_file, file_accessor);
if (!zip_writer)
if (!zip_writer) {
return false;
}
}
zip_writer->SetProgressCallback(params.progress_callback,
@ -148,7 +275,7 @@ bool Zip(const ZipParams& params) {
zip_writer->SetRecursive(params.recursive);
zip_writer->ContinueOnError(params.continue_on_error);
if (!params.include_hidden_files || params.filter_callback)
if (!params.include_hidden_files || params.filter_callback) {
zip_writer->SetFilterCallback(base::BindRepeating(
[](const ZipParams* const params, const base::FilePath& path) -> bool {
return (params->include_hidden_files || !IsHiddenFile(path)) &&
@ -156,16 +283,19 @@ bool Zip(const ZipParams& params) {
params->filter_callback.Run(params->src_dir.Append(path)));
},
&params));
}
if (params.src_files.empty()) {
// No source items are specified. Zip the entire source directory.
zip_writer->SetRecursive(true);
if (!zip_writer->AddDirectoryContents(base::FilePath()))
if (!zip_writer->AddDirectoryContents(base::FilePath())) {
return false;
}
} else {
// Only zip the specified source items.
if (!zip_writer->AddMixedEntries(params.src_files))
if (!zip_writer->AddMixedEntries(params.src_files)) {
return false;
}
}
return zip_writer->Close();
@ -173,7 +303,8 @@ bool Zip(const ZipParams& params) {
bool Unzip(const base::FilePath& src_file,
const base::FilePath& dest_dir,
UnzipOptions options) {
UnzipOptions options,
UnzipSymlinkOption symlink_option) {
base::File file(src_file, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid()) {
PLOG(ERROR) << "Cannot open " << Redact(src_file) << ": "
@ -184,63 +315,27 @@ bool Unzip(const base::FilePath& src_file,
DLOG_IF(WARNING, !base::IsDirectoryEmpty(dest_dir))
<< "ZIP extraction directory is not empty: " << dest_dir;
return Unzip(file.GetPlatformFile(),
base::BindRepeating(&CreateFilePathWriterDelegate, dest_dir),
base::BindRepeating(&CreateDirectory, dest_dir),
std::move(options));
base::RepeatingCallback<bool(const base::FilePath&, const base::FilePath&)>
symlink_creator;
#if defined(OS_POSIX)
if (symlink_option == UnzipSymlinkOption::PRESERVE) {
symlink_creator = base::BindRepeating(&CreateSymbolicLink, dest_dir);
}
#endif // defined(OS_POSIX)
return UnzipImpl(file.GetPlatformFile(),
base::BindRepeating(&CreateFilePathWriterDelegate, dest_dir),
base::BindRepeating(&CreateDirectory, dest_dir),
std::move(options), symlink_creator);
}
bool Unzip(const base::PlatformFile& src_file,
WriterFactory writer_factory,
DirectoryCreator directory_creator,
UnzipOptions options) {
ZipReader reader;
reader.SetEncoding(std::move(options.encoding));
reader.SetPassword(std::move(options.password));
if (!reader.OpenFromPlatformFile(src_file)) {
LOG(ERROR) << "Cannot open ZIP from file handle " << src_file;
return false;
}
while (const ZipReader::Entry* const entry = reader.Next()) {
if (entry->is_unsafe) {
LOG(ERROR) << "Found unsafe entry " << Redact(entry->path) << " in ZIP";
if (!options.continue_on_error)
return false;
continue;
}
if (options.filter && !options.filter.Run(entry->path)) {
VLOG(1) << "Skipped ZIP entry " << Redact(entry->path);
continue;
}
if (entry->is_directory) {
// It's a directory.
if (!directory_creator.Run(entry->path)) {
LOG(ERROR) << "Cannot create directory " << Redact(entry->path);
if (!options.continue_on_error)
return false;
}
continue;
}
// It's a file.
std::unique_ptr<WriterDelegate> writer = writer_factory.Run(entry->path);
if (!writer ||
(options.progress ? !reader.ExtractCurrentEntryWithListener(
writer.get(), options.progress)
: !reader.ExtractCurrentEntry(writer.get()))) {
LOG(ERROR) << "Cannot extract file " << Redact(entry->path)
<< " from ZIP";
if (!options.continue_on_error)
return false;
}
}
return reader.ok();
return UnzipImpl(src_file, writer_factory, directory_creator,
std::move(options),
/*symlink_creator=*/{});
}
bool ZipWithFilterCallback(const base::FilePath& src_dir,

View File

@ -193,6 +193,19 @@ struct UnzipOptions {
bool continue_on_error = false;
};
// Option of the Unzip function to control handling of symbolic link entries.
enum class UnzipSymlinkOption {
// Don't preserve internal symbolic links. On POSIX, consider symbolic link
// entries as errors. On other platforms, links are not differentiated from
// regular files.
DONT_PRESERVE,
#if defined(OS_POSIX)
// Preserve internal symbolic links. Links which point outside of the
// extraction directory or specify an absolute target are rejected.
PRESERVE,
#endif
};
typedef base::RepeatingCallback<std::unique_ptr<WriterDelegate>(
const base::FilePath&)>
WriterFactory;
@ -206,13 +219,16 @@ bool Unzip(const base::PlatformFile& zip_file,
DirectoryCreator directory_creator,
UnzipOptions options = {});
// Unzips the contents of |zip_file| into |dest_dir|.
// This function does not overwrite any existing file.
// A filename collision will result in an error.
// Therefore, |dest_dir| should initially be an empty directory.
bool Unzip(const base::FilePath& zip_file,
const base::FilePath& dest_dir,
UnzipOptions options = {});
// Unzips the contents of |zip_file| into |dest_dir|. This function does not
// overwrite any existing file. A filename collision will result in an error.
// Therefore, |dest_dir| should initially be an empty directory. If
// |allow_symlinks| is set internal symbolics links will be preserved. Else,
// symbolic link entries are considered errors.
bool Unzip(
const base::FilePath& zip_file,
const base::FilePath& dest_dir,
UnzipOptions options = {},
UnzipSymlinkOption symlink_option = UnzipSymlinkOption::DONT_PRESERVE);
} // namespace zip

View File

@ -7,6 +7,8 @@
#include <string>
#include <stdint.h>
#include "base/time/time.h"
#include "build/build_config.h"
@ -79,8 +81,10 @@ bool ZipOpenNewFileInZip(zipFile zip_file,
// PNG...) then the compression method is simply kStored.
Compression GetCompressionMethod(const base::FilePath& path);
const int kZipMaxPath = 256;
const int kZipBufSize = 8192;
// ZIP file names are up to 2^16 - 1, buffers should be 1 larger (for \0).
inline constexpr int kZipMaxPath = UINT16_MAX + 1;
inline constexpr int kZipBufSize = 8192;
} // namespace internal
} // namespace zip

View File

@ -9,6 +9,7 @@
#include <utility>
#include "base/check.h"
#include "base/containers/heap_array.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
@ -209,16 +210,17 @@ bool ZipReader::OpenEntry() {
// Get entry info.
unz_file_info64 info = {};
char path_in_zip[internal::kZipMaxPath] = {};
auto path_in_zip = base::HeapArray<char>::WithSize(internal::kZipMaxPath);
if (const UnzipError err{unzGetCurrentFileInfo64(
zip_file_, &info, path_in_zip, sizeof(path_in_zip) - 1, nullptr, 0,
nullptr, 0)};
zip_file_, &info, path_in_zip.data(), path_in_zip.size() - 1,
nullptr, 0, nullptr, 0)};
err != UNZ_OK) {
LOG(ERROR) << "Cannot get entry from ZIP: " << err;
return false;
}
entry_.path_in_original_encoding = path_in_zip;
DCHECK(path_in_zip[info.size_filename] == '\0');
entry_.path_in_original_encoding = path_in_zip.data();
// Convert path from original encoding to Unicode.
std::u16string path_in_utf16;
@ -260,8 +262,10 @@ bool ZipReader::OpenEntry() {
#if defined(OS_POSIX)
entry_.posix_mode = (info.external_fa >> 16L) & (S_IRWXU | S_IRWXG | S_IRWXO);
entry_.is_symbolic_link = S_ISLNK(info.external_fa >> 16L);
#else
entry_.posix_mode = 0;
entry_.is_symbolic_link = false;
#endif
return true;

View File

@ -143,6 +143,9 @@ class ZipReader {
// Entry POSIX permissions (POSIX systems only).
int posix_mode;
// True if the entry is a symbolic link (POSIX systems only).
bool is_symbolic_link = false;
};
ZipReader();

View File

@ -887,6 +887,31 @@ TEST_F(ZipReaderTest, WrongCrc) {
EXPECT_EQ("This file has been changed after its CRC was computed.", contents);
}
// The Unicode Path Extra field overrides the regular filename. Make sure the
// size_filename field is also correctly updated (ZipReader has a DCHECK for
// this).
TEST_F(ZipReaderTest, WrongFilenameLength) {
static const char test_data[] = {
0x50, 0x4b, 0x03, 0x04, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x71,
0x91, 0x4e, 0xbc, 0x2c, 0x7f, 0x06, 0x09, 0x00, 0x00, 0x00, 0x09, 0x00,
0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xc8, 0xfe, 0x20, 0xc8, 0xfe, 0xc8,
0xfe, 0x2e, 0x74, 0x78, 0x74, 0xed, 0x95, 0x9c, 0xea, 0xb5, 0xad, 0xeb,
0xa7, 0x90, 0x50, 0x4b, 0x01, 0x02, 0x3f, 0x03, 0x0a, 0x03, 0x00, 0x00,
0x00, 0x00, 0xd0, 0x71, 0x91, 0x4e, 0xbc, 0x2c, 0x7f, 0x06, 0x09, 0x00,
0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x17, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0xc9, 0x81, 0x00, 0x00, 0x00, 0x00,
0xc8, 0xfe, 0x20, 0xc8, 0xfe, 0xc8, 0xfe, 0x2e, 0x74, 0x78, 0x74, 0x75,
0x70, 0x13, 0x00, 0x01, 0xe9, 0x73, 0xbf, 0xc8, 0xec, 0x83, 0x88, 0x20,
0xeb, 0xac, 0xb8, 0xec, 0x84, 0x9c, 0x2e, 0x74, 0x78, 0x74, 0x50, 0x4b,
0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x50, 0x00,
0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00};
std::string test_string(test_data, sizeof(test_data));
ZipReader reader;
ASSERT_TRUE(reader.OpenFromString(test_string));
reader.Next();
}
class FileWriterDelegateTest : public ::testing::Test {
protected:
void SetUp() override {

View File

@ -60,8 +60,9 @@ std::vector<std::string> GetRelativePaths(const base::FilePath& dir,
bool CreateFile(const std::string& content,
base::FilePath* file_path,
base::File* file) {
if (!base::CreateTemporaryFile(file_path))
if (!base::CreateTemporaryFile(file_path)) {
return false;
}
if (!base::WriteFile(*file_path, content)) {
return false;
@ -93,8 +94,9 @@ class ProgressWriterDelegate : public zip::WriterDelegate {
private:
void LogProgressIfNecessary() {
const base::TimeTicks now = base::TimeTicks::Now();
if (next_progress_report_time_ > now)
if (next_progress_report_time_ > now) {
return;
}
next_progress_report_time_ = now + progress_period_;
LogProgress();
@ -184,8 +186,9 @@ class VirtualFileSystem : public zip::FileAccessor {
DCHECK(subdirs);
const auto it = file_tree_.find(path);
if (it == file_tree_.end())
if (it == file_tree_.end()) {
return false;
}
for (const base::FilePath& file : it->second.files) {
DCHECK(!file.empty());
@ -204,8 +207,9 @@ class VirtualFileSystem : public zip::FileAccessor {
DCHECK(!path.IsAbsolute());
DCHECK(info);
if (!file_tree_.count(path))
if (!file_tree_.count(path)) {
return false;
}
info->is_directory = !files_.count(path);
info->last_modified =
@ -309,8 +313,9 @@ class ZipTest : public PlatformTest {
size_t expected_count = 0;
for (const base::FilePath& path : zip_contents_) {
if (expect_hidden_files || path.BaseName().value()[0] != '.')
if (expect_hidden_files || path.BaseName().value()[0] != '.') {
++expected_count;
}
}
EXPECT_EQ(expected_count, count);
@ -788,8 +793,8 @@ TEST_F(ZipTest, UnzipMixedPaths) {
"c/NUL", // Disappears on Windows
"nul.very long extension", // Disappears on Windows
#ifndef OS_APPLE
"CASE", // Conflicts with "Case"
"case", // Conflicts with "Case"
"CASE", // Conflicts with "Case"
"case", // Conflicts with "Case"
#endif
#endif
" NUL.txt", //
@ -956,6 +961,90 @@ TEST_F(ZipTest, UnzipOnlyDirectories) {
EXPECT_FALSE(base::PathExists(dir_foo_bar.AppendASCII("quux.txt")));
}
#if defined(OS_POSIX)
TEST_F(ZipTest, UnzipSymlinks) {
ASSERT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII("symlinks.zip"),
test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::PRESERVE));
EXPECT_TRUE(base::PathExists(test_dir_.AppendASCII("a.txt")));
EXPECT_TRUE(base::PathExists(test_dir_.AppendASCII("b.txt")));
EXPECT_TRUE(base::PathExists(test_dir_.AppendASCII("dir/c.txt")));
base::FilePath target;
ASSERT_TRUE(
base::ReadSymbolicLink(test_dir_.AppendASCII("dir/a_link"), &target));
EXPECT_EQ(target.AsUTF8Unsafe(), "../a.txt");
ASSERT_TRUE(base::ReadSymbolicLink(test_dir_.AppendASCII("b_link"), &target));
EXPECT_EQ(target.AsUTF8Unsafe(), "b.txt");
ASSERT_TRUE(base::ReadSymbolicLink(test_dir_.AppendASCII("c_link"), &target));
EXPECT_EQ(target.AsUTF8Unsafe(), "dir/c.txt");
}
TEST_F(ZipTest, UnzipRejectsSymlinks) {
EXPECT_FALSE(zip::Unzip(GetDataDirectory().AppendASCII("symlinks.zip"),
test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::DONT_PRESERVE));
}
TEST_F(ZipTest, UnzipSkipsSymlinks) {
ASSERT_TRUE(zip::Unzip(GetDataDirectory().AppendASCII("symlinks.zip"),
test_dir_,
{
.continue_on_error = true,
},
zip::UnzipSymlinkOption::DONT_PRESERVE));
EXPECT_TRUE(base::PathExists(test_dir_.AppendASCII("a.txt")));
EXPECT_TRUE(base::PathExists(test_dir_.AppendASCII("b.txt")));
EXPECT_TRUE(base::PathExists(test_dir_.AppendASCII("dir/c.txt")));
EXPECT_FALSE(base::PathExists(test_dir_.AppendASCII("dir/a_link")));
EXPECT_FALSE(base::PathExists(test_dir_.AppendASCII("b_link")));
EXPECT_FALSE(base::PathExists(test_dir_.AppendASCII("c_link")));
}
TEST_F(ZipTest, UnzipSymlinksRejectsEvilRelativePath) {
const base::FilePath zip_path =
GetDataDirectory().AppendASCII("symlink_evil_relative_path.zip");
ASSERT_TRUE(base::PathExists(zip_path));
EXPECT_FALSE(zip::Unzip(zip_path, test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::PRESERVE));
}
TEST_F(ZipTest, UnzipSymlinksRejectsAbsolutePath) {
const base::FilePath zip_path =
GetDataDirectory().AppendASCII("symlink_absolute_path.zip");
ASSERT_TRUE(base::PathExists(zip_path));
EXPECT_FALSE(zip::Unzip(zip_path, test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::PRESERVE));
}
TEST_F(ZipTest, UnzipSymlinksRejectsSymlinkTooLarge) {
const base::FilePath zip_path =
GetDataDirectory().AppendASCII("symlink_too_large.zip");
ASSERT_TRUE(base::PathExists(zip_path));
EXPECT_FALSE(zip::Unzip(zip_path, test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::PRESERVE));
}
TEST_F(ZipTest, UnzipSymlinksNoFollowOwnLink) {
const base::FilePath zip_path =
GetDataDirectory().AppendASCII("symlink_follow_own_link.zip");
ASSERT_TRUE(base::PathExists(zip_path));
EXPECT_FALSE(zip::Unzip(zip_path, test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::PRESERVE));
}
TEST_F(ZipTest, UnzipSymlinksRejectsDuplicateLink) {
const base::FilePath zip_path =
GetDataDirectory().AppendASCII("symlink_duplicate_link.zip");
ASSERT_TRUE(base::PathExists(zip_path));
EXPECT_FALSE(zip::Unzip(zip_path, test_dir_, /*options=*/{},
zip::UnzipSymlinkOption::PRESERVE));
}
#endif // defined(OS_POSIX)
// Tests that a ZIP archive containing SJIS-encoded file names can be correctly
// extracted if the encoding is specified.
TEST_F(ZipTest, UnzipSjis) {

8
deps/zlib/gzguts.h vendored
View File

@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
* Copyright (C) 2004-2019 Mark Adler
* Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -210,9 +210,5 @@ char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
#ifdef INT_MAX
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else
unsigned ZLIB_INTERNAL gz_intmax(void);
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif
#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())

12
deps/zlib/gzlib.c vendored
View File

@ -1,5 +1,5 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004-2019 Mark Adler
* Copyright (C) 2004-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -566,20 +566,20 @@ void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
#endif
}
#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax(void) {
unsigned p, q;
p = 1;
#ifdef INT_MAX
return INT_MAX;
#else
unsigned p = 1, q;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
}
#endif
}

View File

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2023 Mark Adler
* Copyright (C) 1995-2024 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.3.0.1 Copyright 1995-2023 Mark Adler ";
" inflate 1.3.1 Copyright 1995-2024 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@ -57,7 +57,7 @@ int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 70, 200};
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 77};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,

View File

@ -41,7 +41,7 @@ typedef struct {
examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 10 15" for literal/length codes
returns returns 1332, and "enough 30 9 15" for distance codes returns 592.
returns 1332, and "enough 30 9 15" for distance codes returns 592.
The initial root table size (10 or 9) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and

View File

@ -1,42 +0,0 @@
From 8304bdda5293ffd5b3efce8e4f54904b387029d6 Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans@chromium.org>
Date: Wed, 23 Sep 2020 16:36:38 +0200
Subject: [PATCH] Avoid crashing in check_match when prev_match == -1
prev_match can be set to -1 after sliding the window. In that case, the
window has slid past the first byte of the last match, which means it
cannot be compared in check_match.
This would cause zlib to crash on some inputs to deflate when built
with ZLIB_DEBUG enabled.
Check for this situation and avoid crashing by not trying to compare
the first byte.
Bug: 1113142
---
third_party/zlib/deflate.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c
index cfdd2f46b230..d70732ec6fc2 100644
--- a/third_party/zlib/deflate.c
+++ b/third_party/zlib/deflate.c
@@ -2060,7 +2060,13 @@ local block_state deflate_slow(s, flush)
uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
/* Do not insert strings in hash table beyond this. */
- check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+ if (s->prev_match == -1) {
+ /* The window has slid one byte past the previous match,
+ * so the first byte cannot be compared. */
+ check_match(s, s->strstart, s->prev_match+1, s->prev_length-1);
+ } else {
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+ }
_tr_tally_dist(s, s->strstart -1 - s->prev_match,
s->prev_length - MIN_MATCH, bflush);
--
2.28.0.681.g6f77f65b4e-goog

View File

@ -21,6 +21,20 @@ Date: Thu May 12 03:29:52 2022 +0000
Commit-Queue: Alex Danilo <adanilo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1002476}
commit 5a56f75b0da23a10f2c6d9068029a00e53425ddf
Author: Hans Wennborg <hans@chromium.org>
Date: Fri May 16 15:48:19 2025 +0200
[minizip] Set filename length when using the Unicode Path Extra field
This is a follow-up to crrev.com/1002476 which added support for parsing
the Unicode Path Extra field, which overrides the regular filename. It
also needs to update the filename length.
Bug: 40623474
Change-Id: Ifab65f470736b45b1b51a1cc130a5753a2b20583
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6553931
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
@ -93,6 +107,8 @@ index c8a01b23efd42..42677cff82c96 100644
+ {
+ uLong uSizeRead;
+
+ file_info.size_filename = fileNameSize;
+
+ if (fileNameSize < fileNameBufferSize)
+ {
+ *(szFileName + fileNameSize) = '\0';

View File

@ -0,0 +1,82 @@
commit 410a23e8a442e3de4f8df29339946a7d826120d0
Author: Joshua Pawlicki <waffles@chromium.org>
Date: Wed May 14 10:58:18 2025 -0700
[zip]: Allow zip64 files to have prepended content.
This was already supported for non-zip64 files.
Fixed: 414848094
Change-Id: I3bd79f4b5175d8abca8d8e81f26373037868dcf8
Cq-Include-Trybots: luci.chromium.try:ios-blink-dbg-fyi
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6533087
Commit-Queue: Joshua Pawlicki <waffles@chromium.org>
Auto-Submit: Joshua Pawlicki <waffles@chromium.org>
Reviewed-by: Hans Wennborg <hans@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1460236}
commit 3daf10f4a4cd6dbfaaaef6a90091f7c6c3148a24
Author: Hans Wennborg <hans@chromium.org>
Date: Fri May 16 15:35:36 2025 +0200
[minizip] Fix possible infinite loop in unz64local_SearchCentralDir64
This is a follow-up to crrev.com/1460236, where `uPosFound - 48` could
overflow, resulting in a possible readSize of 3, which meant the loop
did not make progress.
Bug: 414848094
Change-Id: Icda653b2c9ac59161fb2aba9ac287fe510ee8653
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6554217
diff --git a/third_party/zlib/contrib/minizip/unzip.c b/third_party/zlib/contrib/minizip/unzip.c
index a39e1752f6d2e..2c8a73e87e011 100644
--- a/third_party/zlib/contrib/minizip/unzip.c
+++ b/third_party/zlib/contrib/minizip/unzip.c
@@ -482,6 +482,44 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (uL != 1)
return CENTRALDIRINVALID;
+ /* If bytes are pre-pended to the archive, relativeOffset must be advanced
+ by that many bytes. The central dir must exist between the specified
+ relativeOffset and uPosFound. */
+ const int BUFSIZE = 1024 * 4;
+ buf = (unsigned char*)ALLOC(BUFSIZE);
+ if (buf==NULL)
+ return CENTRALDIRINVALID;
+ if (relativeOffset > uPosFound)
+ return CENTRALDIRINVALID;
+ // Zip64 EOCDR is at least 48 bytes long.
+ while (relativeOffset + 48 <= uPosFound) {
+ int found = 0;
+ uLong uReadSize = uPosFound - relativeOffset;
+ if (uReadSize > BUFSIZE) {
+ uReadSize = BUFSIZE;
+ }
+ if (ZSEEK64(*pzlib_filefunc_def, filestream, relativeOffset, ZLIB_FILEFUNC_SEEK_SET) != 0) {
+ break;
+ }
+ if (ZREAD64(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize) {
+ break;
+ }
+ for (int i = 0; i < uReadSize - 3; ++i) {
+ // Looking for 0x06064b50, the Zip64 EOCDR signature.
+ if (buf[i] == 0x50 && buf[i + 1] == 0x4b &&
+ buf[i + 2] == 0x06 && buf[i + 3] == 0x06)
+ {
+ relativeOffset += i;
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+ // Re-read the last 3 bytes, in case they're the front of the signature.
+ relativeOffset += uReadSize - 3;
+ }
+ free(buf);
+
/* Goto end of central directory record */
if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
return CENTRALDIRINVALID;

View File

@ -303,7 +303,7 @@ static void error(const char *msg) {
#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
/* Try compressing the input file at once using mmap. Return Z_OK if
* if success, Z_ERRNO otherwise.
* success, Z_ERRNO otherwise.
*/
static int gz_compress_mmap(FILE *in, gzFile out) {
int len;

53
deps/zlib/trees.c vendored
View File

@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2021 Jean-loup Gailly
* Copyright (C) 1995-2024 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -141,11 +141,18 @@ local TCONST static_tree_desc static_bl_desc =
* Output a short LSB first on the stream.
* IN assertion: there is enough room in pendingBuf.
*/
#if defined(DEFLATE_CHUNK_WRITE_64LE)
#define put_short(s, w) { \
uint16_t data = (uint16_t)(w); \
zmemcpy(&s->pending_buf[s->pending], &data, sizeof(data)); \
s->pending += 2; \
}
#else
#define put_short(s, w) { \
put_byte(s, (uch)((w) & 0xff)); \
put_byte(s, (uch)((ush)(w) >> 8)); \
}
#endif /* DEFLATE_CHUNK_WRITE_64LE */
/* ===========================================================================
* Reverse the first len bits of a code, using straightforward code (a faster
* method would use a table)
@ -164,6 +171,13 @@ local unsigned bi_reverse(unsigned code, int len) {
* Flush the bit buffer, keeping at most 7 bits in it.
*/
local void bi_flush(deflate_state *s) {
#if defined(DEFLATE_CHUNK_WRITE_64LE)
while (s->bi_valid >= 16) {
put_short(s, s->bi_buf);
s->bi_buf >>= 16;
s->bi_valid -= 16;
}
#endif /* DEFLATE_CHUNK_WRITE_64LE */
if (s->bi_valid == 16) {
put_short(s, s->bi_buf);
s->bi_buf = 0;
@ -173,12 +187,21 @@ local void bi_flush(deflate_state *s) {
s->bi_buf >>= 8;
s->bi_valid -= 8;
}
Assert(s->bi_valid >= 0 && s->bi_valid <= 7, "bad bi_flush");
}
/* ===========================================================================
* Flush the bit buffer and align the output on a byte boundary
*/
local void bi_windup(deflate_state *s) {
#if defined(DEFLATE_CHUNK_WRITE_64LE)
while (s->bi_valid >= 16) {
put_short(s, s->bi_buf);
s->bi_buf >>= 16;
s->bi_valid -= 16;
}
#endif /* DEFLATE_CHUNK_WRITE_64LE */
if (s->bi_valid > 8) {
put_short(s, s->bi_buf);
} else if (s->bi_valid > 0) {
@ -248,7 +271,28 @@ local void gen_trees_header(void);
* Send a value on a given number of bits.
* IN assertion: length <= 16 and value fits in length bits.
*/
#if defined(DEFLATE_CHUNK_WRITE_64LE)
local void send_bits(deflate_state *s, uint64_t value, int length)
{
Tracevv((stderr," l %2d v %4llx ", length, (unsigned long long)value));
Assert(s->bi_valid >= 0 && s->bi_valid <= 63, "invalid bi_valid");
Assert(length > 0 && length <= 15, "invalid length");
#ifdef ZLIB_DEBUG
s->bits_sent += (ulg)length;
#endif
s->bi_buf |= (value << s->bi_valid);
s->bi_valid += length;
if (s->bi_valid >= Buf_size) {
zmemcpy(&s->pending_buf[s->pending], &s->bi_buf, sizeof(s->bi_buf));
s->pending += 8;
s->bi_valid -= Buf_size;
s->bi_buf = value >> (length - s->bi_valid);
}
Assert(s->bi_valid >= 0 && s->bi_valid <= 63, "invalid bi_valid");
}
#elif defined(ZLIB_DEBUG)
local void send_bits(deflate_state *s, int value, int length) {
Tracevv((stderr," l %2d v %4x ", length, value));
Assert(length > 0 && length <= 15, "invalid length");
@ -268,8 +312,7 @@ local void send_bits(deflate_state *s, int value, int length) {
s->bi_valid += length;
}
}
#else /* !ZLIB_DEBUG */
#else /* !ZLIB_DEBUG && !DEFLATE_CHUNK_WRITE_64LE */
#define send_bits(s, value, length) \
{ int len = length;\
if (s->bi_valid > (int)Buf_size - len) {\
@ -283,7 +326,7 @@ local void send_bits(deflate_state *s, int value, int length) {
s->bi_valid += len;\
}\
}
#endif /* ZLIB_DEBUG */
#endif /* DEFLATE_CHUNK_WRITE_64LE */
/* the arguments must not have side effects */

10
deps/zlib/zconf.h vendored
View File

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -312,14 +312,6 @@
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have

View File

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -302,14 +302,6 @@
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have

10
deps/zlib/zconf.h.in vendored
View File

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -300,14 +300,6 @@
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have

6
deps/zlib/zlib.3 vendored
View File

@ -1,4 +1,4 @@
.TH ZLIB 3 "xx Aug 2023"
.TH ZLIB 3 "22 Jan 2024"
.SH NAME
zlib \- compression/decompression library
.SH SYNOPSIS
@ -105,9 +105,9 @@ before asking for help.
Send questions and/or comments to zlib@gzip.org,
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
.SH AUTHORS AND LICENSE
Version 1.2.3.0.1
Version 1.3.1
.LP
Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
.LP
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages

8
deps/zlib/zlib.gyp vendored
View File

@ -139,7 +139,7 @@
# ],
# }, # zlib_crc32_simd
{
'target_name': 'zlib_inflate_chunk_simd',
'target_name': 'zlib_data_chunk_simd',
'type': 'static_library',
'conditions': [
['target_arch in "ia32 x64" and OS!="ios"', {
@ -172,9 +172,9 @@
'include_dirs': [ '<(ZLIB_ROOT)' ],
},
'sources': [
'<!@pymod_do_main(GN-scraper "<(ZLIB_ROOT)/BUILD.gn" "\\"zlib_inflate_chunk_simd\\".*?sources = ")',
'<!@pymod_do_main(GN-scraper "<(ZLIB_ROOT)/BUILD.gn" "\\"zlib_data_chunk_simd\\".*?sources = ")',
],
}, # zlib_inflate_chunk_simd
}, # zlib_data_chunk_simd
{
'target_name': 'zlib',
'type': 'static_library',
@ -203,7 +203,7 @@
}],
# Incorporate optimizations where possible.
['(target_arch in "ia32 x64" and OS!="ios") or arm_fpu=="neon"', {
'dependencies': [ 'zlib_inflate_chunk_simd' ],
'dependencies': [ 'zlib_data_chunk_simd' ],
'sources': [ '<(ZLIB_ROOT)/slide_hash_simd.h' ]
}, {
'defines': [ 'CPU_NO_SIMD' ],

24
deps/zlib/zlib.h vendored
View File

@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.3.0.1, August xxth, 2023
version 1.3.1, January 22nd, 2024
Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler
Copyright (C) 1995-2024 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -37,12 +37,12 @@
extern "C" {
#endif
#define ZLIB_VERSION "1.3.0.1-motley"
#define ZLIB_VERNUM 0x1301
#define ZLIB_VERSION "1.3.1"
#define ZLIB_VERNUM 0x1310
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 3
#define ZLIB_VER_REVISION 0
#define ZLIB_VER_SUBREVISION 1
#define ZLIB_VER_REVISION 1
#define ZLIB_VER_SUBREVISION 0
/*
The 'zlib' compression library provides in-memory compression and
@ -935,10 +935,10 @@ ZEXTERN int ZEXPORT inflateSync(z_streamp strm);
inflateSync returns Z_OK if a possible full flush point has been found,
Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
In the success case, the application may save the current current value of
total_in which indicates where valid compressed data was found. In the
error case, the application may repeatedly call inflateSync, providing more
input each time, until success or end of the input data.
In the success case, the application may save the current value of total_in
which indicates where valid compressed data was found. In the error case,
the application may repeatedly call inflateSync, providing more input each
time, until success or end of the input data.
*/
ZEXTERN int ZEXPORT inflateCopy(z_streamp dest,
@ -1757,14 +1757,14 @@ ZEXTERN uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2);
seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
len2.
len2. len2 must be non-negative.
*/
/*
ZEXTERN uLong ZEXPORT crc32_combine_gen(z_off_t len2);
Return the operator corresponding to length len2, to be used with
crc32_combine_op().
crc32_combine_op(). len2 must be non-negative.
*/
ZEXTERN uLong ZEXPORT crc32_combine_op(uLong crc1, uLong crc2, uLong op);

200
deps/zlib/zlib.map vendored
View File

@ -1,100 +1,100 @@
ZLIB_1.2.0 {
global:
compressBound;
deflateBound;
inflateBack;
inflateBackEnd;
inflateBackInit_;
inflateCopy;
local:
deflate_copyright;
inflate_copyright;
inflate_fast;
inflate_table;
zcalloc;
zcfree;
z_errmsg;
gz_error;
gz_intmax;
_*;
};
ZLIB_1.2.0.2 {
gzclearerr;
gzungetc;
zlibCompileFlags;
} ZLIB_1.2.0;
ZLIB_1.2.0.8 {
deflatePrime;
} ZLIB_1.2.0.2;
ZLIB_1.2.2 {
adler32_combine;
crc32_combine;
deflateSetHeader;
inflateGetHeader;
} ZLIB_1.2.0.8;
ZLIB_1.2.2.3 {
deflateTune;
gzdirect;
} ZLIB_1.2.2;
ZLIB_1.2.2.4 {
inflatePrime;
} ZLIB_1.2.2.3;
ZLIB_1.2.3.3 {
adler32_combine64;
crc32_combine64;
gzopen64;
gzseek64;
gztell64;
inflateUndermine;
} ZLIB_1.2.2.4;
ZLIB_1.2.3.4 {
inflateReset2;
inflateMark;
} ZLIB_1.2.3.3;
ZLIB_1.2.3.5 {
gzbuffer;
gzoffset;
gzoffset64;
gzclose_r;
gzclose_w;
} ZLIB_1.2.3.4;
ZLIB_1.2.5.1 {
deflatePending;
} ZLIB_1.2.3.5;
ZLIB_1.2.5.2 {
deflateResetKeep;
gzgetc_;
inflateResetKeep;
} ZLIB_1.2.5.1;
ZLIB_1.2.7.1 {
inflateGetDictionary;
gzvprintf;
} ZLIB_1.2.5.2;
ZLIB_1.2.9 {
inflateCodesUsed;
inflateValidate;
uncompress2;
gzfread;
gzfwrite;
deflateGetDictionary;
adler32_z;
crc32_z;
} ZLIB_1.2.7.1;
ZLIB_1.2.12 {
crc32_combine_gen;
crc32_combine_gen64;
crc32_combine_op;
} ZLIB_1.2.9;
ZLIB_1.2.0 {
global:
compressBound;
deflateBound;
inflateBack;
inflateBackEnd;
inflateBackInit_;
inflateCopy;
local:
deflate_copyright;
inflate_copyright;
inflate_fast;
inflate_table;
zcalloc;
zcfree;
z_errmsg;
gz_error;
gz_intmax;
_*;
};
ZLIB_1.2.0.2 {
gzclearerr;
gzungetc;
zlibCompileFlags;
} ZLIB_1.2.0;
ZLIB_1.2.0.8 {
deflatePrime;
} ZLIB_1.2.0.2;
ZLIB_1.2.2 {
adler32_combine;
crc32_combine;
deflateSetHeader;
inflateGetHeader;
} ZLIB_1.2.0.8;
ZLIB_1.2.2.3 {
deflateTune;
gzdirect;
} ZLIB_1.2.2;
ZLIB_1.2.2.4 {
inflatePrime;
} ZLIB_1.2.2.3;
ZLIB_1.2.3.3 {
adler32_combine64;
crc32_combine64;
gzopen64;
gzseek64;
gztell64;
inflateUndermine;
} ZLIB_1.2.2.4;
ZLIB_1.2.3.4 {
inflateReset2;
inflateMark;
} ZLIB_1.2.3.3;
ZLIB_1.2.3.5 {
gzbuffer;
gzoffset;
gzoffset64;
gzclose_r;
gzclose_w;
} ZLIB_1.2.3.4;
ZLIB_1.2.5.1 {
deflatePending;
} ZLIB_1.2.3.5;
ZLIB_1.2.5.2 {
deflateResetKeep;
gzgetc_;
inflateResetKeep;
} ZLIB_1.2.5.1;
ZLIB_1.2.7.1 {
inflateGetDictionary;
gzvprintf;
} ZLIB_1.2.5.2;
ZLIB_1.2.9 {
inflateCodesUsed;
inflateValidate;
uncompress2;
gzfread;
gzfwrite;
deflateGetDictionary;
adler32_z;
crc32_z;
} ZLIB_1.2.7.1;
ZLIB_1.2.12 {
crc32_combine_gen;
crc32_combine_gen64;
crc32_combine_op;
} ZLIB_1.2.9;

4
deps/zlib/zutil.h vendored
View File

@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
* Copyright (C) 1995-2024 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@ -71,7 +71,7 @@ typedef unsigned long ulg;
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_MSG(err) z_errmsg[(err) < -6 || (err) > 2 ? 9 : 2 - (err)]
#define ERR_RETURN(strm,err) \
return (strm->msg = ERR_MSG(err), (err))

View File

@ -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.0.1-motley-780819f"
#define ZLIB_VERSION "1.3.1-470d3a2"
#endif // SRC_ZLIB_VERSION_H_