From d86027fe906469b730f20fd4ec0150913414619d Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Mon, 9 Aug 2021 06:59:10 -0700 Subject: [PATCH] Integrate Chromium Zlib changes --- third_party/zlib/chunkcopy.internal.h | 25 +++++++++++++++++ third_party/zlib/deflate.c | 39 ++++++++++++++++++--------- third_party/zlib/inffastchunk.c | 2 +- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/third_party/zlib/chunkcopy.internal.h b/third_party/zlib/chunkcopy.internal.h index 1439fe6a7..f8532d3c4 100644 --- a/third_party/zlib/chunkcopy.internal.h +++ b/third_party/zlib/chunkcopy.internal.h @@ -98,6 +98,10 @@ static inline unsigned char *chunkcopy_core_safe(unsigned char *out, Assert(out + len <= limit, "chunk copy exceeds safety limit"); if ((limit - out) < (ptrdiff_t)CHUNKCOPY_CHUNK_SIZE) { const unsigned char *Z_RESTRICT rfrom = from; + Assert((uintptr_t)out - (uintptr_t)from >= len, + "invalid restrict in chunkcopy_core_safe"); + Assert((uintptr_t)from - (uintptr_t)out >= len, + "invalid restrict in chunkcopy_core_safe"); if (len & 8) { Z_BUILTIN_MEMCPY(out, rfrom, 8); out += 8; @@ -273,6 +277,10 @@ static inline unsigned char *chunkset_core(unsigned char *out, unsigned period, static inline unsigned char *chunkcopy_relaxed( unsigned char *Z_RESTRICT out, const unsigned char *Z_RESTRICT from, unsigned len) { + Assert((uintptr_t)out - (uintptr_t)from >= len, + "invalid restrict in chunkcopy_relaxed"); + Assert((uintptr_t)from - (uintptr_t)out >= len, + "invalid restrict in chunkcopy_relaxed"); return chunkcopy_core(out, from, len); } @@ -293,6 +301,10 @@ static inline unsigned char *chunkcopy_safe( unsigned char *out, const unsigned char *Z_RESTRICT from, unsigned len, unsigned char *limit) { Assert(out + len <= limit, "chunk copy exceeds safety limit"); + Assert((uintptr_t)out - (uintptr_t)from >= len, + "invalid restrict in chunkcopy_safe"); + Assert((uintptr_t)from - (uintptr_t)out >= len, + "invalid restrict in chunkcopy_safe"); return chunkcopy_core_safe(out, from, len, limit); } @@ -336,6 +348,19 @@ static inline unsigned char *chunkcopy_lapped_safe(unsigned char *out, return chunkcopy_lapped_relaxed(out, dist, len); } +/* TODO(cavalcanti): see crbug.com/1110083. */ +static inline unsigned char *chunkcopy_safe_ugly(unsigned char *out, + unsigned dist, unsigned len, + unsigned char *limit) { + /* Seems to perform better on 64bit. */ + return chunkcopy_lapped_safe(out, dist, len, limit); +} + +/* + * Buffer the input in a uint64_t (8 bytes) in the wide input reading case. + */ +typedef uint64_t inflate_holder_t; + #undef Z_STATIC_ASSERT #undef Z_RESTRICT #undef Z_BUILTIN_MEMCPY diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c index 59dc2d6bc..7ac4f981e 100644 --- a/third_party/zlib/deflate.c +++ b/third_party/zlib/deflate.c @@ -59,6 +59,11 @@ Invented 1990 Phillip Walter Katz\""); * Windows, Comm.ACM, 32,4 (1989) 490-595 */ +#ifdef FASTEST +/* See http://crbug.com/1113596 */ +#error "FASTEST is not supported in Chromium's zlib." +#endif + /* Tail of hash chains */ #define NIL 0 @@ -333,7 +338,9 @@ int deflateInit2(z_streamp strm, int level, int method, int windowBits, s->window = (Bytef *)ZALLOC(strm, s->w_size + window_padding, 2 * sizeof(Byte)); + memset(s->window, 0, (s->w_size + window_padding) * (2 * sizeof(Byte))); s->prev = (Posf *)ZALLOC(strm, s->w_size, sizeof(Pos)); + memset(s->prev, 0, s->w_size * sizeof(Pos)); s->head = (Posf *)ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ @@ -517,7 +524,8 @@ int deflateResetKeep(z_streamp strm) { #ifdef GZIP s->wrap == 2 ? GZIP_STATE : #endif - s->wrap ? INIT_STATE : BUSY_STATE; + s->wrap ? INIT_STATE + : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : @@ -956,14 +964,11 @@ int deflate(z_streamp strm, int flush) { (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - bstate = - s->level == 0 - ? deflate_stored(s, flush) - : s->strategy == Z_HUFFMAN_ONLY - ? deflate_huff(s, flush) - : s->strategy == Z_RLE - ? deflate_rle(s, flush) - : (*(configuration_table[s->level].func))(s, flush); + bstate = s->level == 0 ? deflate_stored(s, flush) + : s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) + : s->strategy == Z_RLE + ? deflate_rle(s, flush) + : (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -1239,7 +1244,12 @@ static uInt longest_match(struct DeflateState *s, IPos cur_match) { * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ - Assert(scan[2] == match[2], "scan[2]?"); + /* When using CRC hashing, scan[2] and match[2] may mismatch, but in + * that case at least one of the other hashed bytes will mismatch + * also. Bytes 0 and 1 were already checked above, and we know there + * are at least four bytes to check otherwise the mismatch would have + * been found by the scan_end comparison above, so: */ + Assert(scan[2] == match[2] || scan[3] != match[3], "scan[2]??"); scan++, match++; do { } while (*(uint16_t *)(scan += 2) == *(ushf *)(match += 2) && @@ -1253,7 +1263,7 @@ static uInt longest_match(struct DeflateState *s, IPos cur_match) { if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend - scan); scan = strend - (MAX_MATCH - 1); -#else /* UNALIGNED_OK */ +#else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len - 1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; @@ -1263,6 +1273,7 @@ static uInt longest_match(struct DeflateState *s, IPos cur_match) { * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ + Assert(*scan == *match || scan[1] != match[1], "match[2]??"); scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; @@ -1710,7 +1721,11 @@ static block_state deflate_slow(struct DeflateState *s, int 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) { + 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); diff --git a/third_party/zlib/inffastchunk.c b/third_party/zlib/inffastchunk.c index 58363b8d9..737a0f6c7 100644 --- a/third_party/zlib/inffastchunk.c +++ b/third_party/zlib/inffastchunk.c @@ -255,7 +255,7 @@ void inflate_fast_chunk(z_streamp strm, unsigned start) { the main copy is near the end. */ out = chunkunroll_relaxed(out, &dist, &len); - out = chunkcopy_safe(out, out - dist, len, limit); + out = chunkcopy_safe_ugly(out, dist, len, limit); } else { /* from points to window, so there is no risk of overlapping pointers requiring memset-like behaviour