Merge "Upgrade zlib to 8cd0fc1ed5ea7b59e4df6428318043a8215254cc" am: b5461d1d89 am: d5e1c71732

Original change: https://android-review.googlesource.com/c/platform/external/zlib/+/1479551

Change-Id: Id14f8c493e50ef444a546ba4f97a333f7c72e9f3
diff --git a/METADATA b/METADATA
index b708053..f6adc14 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@
     type: GIT
     value: "https://chromium.googlesource.com/chromium/src/third_party/zlib/"
   }
-  version: "898c6c0dd91fa0efb38a10949f76102e42cc47f0"
+  version: "8cd0fc1ed5ea7b59e4df6428318043a8215254cc"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 9
-    day: 9
+    month: 10
+    day: 28
   }
 }
diff --git a/contrib/tests/fuzzers/deflate_fuzzer.cc b/contrib/tests/fuzzers/deflate_fuzzer.cc
index 6098ff1..c00e715 100644
--- a/contrib/tests/fuzzers/deflate_fuzzer.cc
+++ b/contrib/tests/fuzzers/deflate_fuzzer.cc
@@ -2,46 +2,73 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <fuzzer/FuzzedDataProvider.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <cassert>
 #include <vector>
 
 #include "third_party/zlib/zlib.h"
 
-static Bytef buffer[256 * 1024] = {0};
+// 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)
 
-// Entry point for LibFuzzer.
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  // zlib's deflate requires non-zero input sizes
-  if (!size)
-    return 0;
-
-  // We need to strip the 'const' for zlib.
-  std::vector<unsigned char> input_buffer{data, data+size};
-
-  uLongf buffer_length = static_cast<uLongf>(sizeof(buffer));
+  FuzzedDataProvider fdp(data, size);
+  int level = fdp.PickValueInArray({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
+  int windowBits = fdp.PickValueInArray({9, 10, 11, 12, 13, 14, 15});
+  int memLevel = fdp.PickValueInArray({1, 2, 3, 4, 5, 6, 7, 8, 9});
+  int strategy = fdp.PickValueInArray(
+      {Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED});
+  std::vector<uint8_t> src = fdp.ConsumeRemainingBytes<uint8_t>();
 
   z_stream stream;
-  stream.next_in = input_buffer.data();
-  stream.avail_in = size;
-  stream.total_in = size;
-  stream.next_out = buffer;
-  stream.avail_out = buffer_length;
-  stream.total_out = buffer_length;
   stream.zalloc = Z_NULL;
   stream.zfree = Z_NULL;
 
-  if (Z_OK != deflateInit(&stream, Z_DEFAULT_COMPRESSION)) {
-    deflateEnd(&stream);
-    assert(false);
+  // Compress the data one byte at a time to exercise the streaming code.
+  int ret =
+      deflateInit2(&stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
+  ASSERT(ret == Z_OK);
+  std::vector<uint8_t> compressed(src.size() * 2 + 1000);
+  stream.next_out = compressed.data();
+  stream.avail_out = compressed.size();
+  for (uint8_t b : src) {
+    stream.next_in = &b;
+    stream.avail_in = 1;
+    ret = deflate(&stream, Z_NO_FLUSH);
+    ASSERT(ret == Z_OK);
   }
-
-  auto deflate_result = deflate(&stream, Z_NO_FLUSH);
+  stream.next_in = Z_NULL;
+  stream.avail_in = 0;
+  ret = deflate(&stream, Z_FINISH);
+  ASSERT(ret == Z_STREAM_END);
+  compressed.resize(compressed.size() - stream.avail_out);
   deflateEnd(&stream);
-  if (Z_OK != deflate_result)
-    assert(false);
+
+  // Verify that the data decompresses correctly.
+  ret = inflateInit2(&stream, windowBits);
+  ASSERT(ret == Z_OK);
+  // Make room for at least one byte so it's never empty.
+  std::vector<uint8_t> decompressed(src.size() + 1);
+  stream.next_in = compressed.data();
+  stream.avail_in = compressed.size();
+  stream.next_out = decompressed.data();
+  stream.avail_out = decompressed.size();
+  ret = inflate(&stream, Z_FINISH);
+  ASSERT(ret == Z_STREAM_END);
+  decompressed.resize(decompressed.size() - stream.avail_out);
+  inflateEnd(&stream);
+
+  ASSERT(decompressed == src);
 
   return 0;
 }
diff --git a/contrib/tests/utils_unittest.cc b/contrib/tests/utils_unittest.cc
index 8d5eab6..35df3a8 100644
--- a/contrib/tests/utils_unittest.cc
+++ b/contrib/tests/utils_unittest.cc
@@ -210,3 +210,211 @@
 
   EXPECT_EQ(src, decompressed);
 }
+
+TEST(ZlibTest, CRCHashAssert) {
+  // The CRC32c of the hex sequences ff,ff,5e,6f and ff,ff,13,ff have the same
+  // lower 15 bits. This means longest_match's assert that match[2] == scan[2]
+  // won't hold. However, such hash collisions are only possible when one of the
+  // other four bytes also mismatch. This tests that zlib's assert handles this
+  // case.
+
+  std::vector<uint8_t> src = {
+      // Random byte; zlib doesn't match at offset 0.
+      123,
+
+      // This has the same hash as the last byte sequence, and the first two and
+      // last two bytes match; though the third and the fourth don't.
+      0xff,
+      0xff,
+      0x5e,
+      0x6f,
+      0x12,
+      0x34,
+
+      // Offer a 5-byte match to bump the next expected match length to 6
+      // (because the two first and two last bytes need to match).
+      0xff,
+      0xff,
+      0x13,
+      0xff,
+      0x12,
+
+      0xff,
+      0xff,
+      0x13,
+      0xff,
+      0x12,
+      0x34,
+  };
+
+  z_stream stream;
+  stream.zalloc = nullptr;
+  stream.zfree = nullptr;
+
+  int ret = deflateInit2(&stream, /*comp level*/ 5, /*method*/ Z_DEFLATED,
+                         /*windowbits*/ -15, /*memlevel*/ 8,
+                         /*strategy*/ Z_DEFAULT_STRATEGY);
+  ASSERT_EQ(ret, Z_OK);
+  std::vector<uint8_t> compressed(100, '\0');
+  stream.next_out = compressed.data();
+  stream.avail_out = compressed.size();
+  stream.next_in = src.data();
+  stream.avail_in = src.size();
+  ret = deflate(&stream, Z_FINISH);
+  ASSERT_EQ(ret, Z_STREAM_END);
+  compressed.resize(compressed.size() - stream.avail_out);
+  deflateEnd(&stream);
+
+  ret = inflateInit2(&stream, /*windowbits*/ -15);
+  ASSERT_EQ(ret, Z_OK);
+  std::vector<uint8_t> decompressed(src.size(), '\0');
+  stream.next_in = compressed.data();
+  stream.avail_in = compressed.size();
+  stream.next_out = decompressed.data();
+  stream.avail_out = decompressed.size();
+  ret = inflate(&stream, Z_FINISH);
+  ASSERT_EQ(ret, Z_STREAM_END);
+  EXPECT_EQ(0U, stream.avail_out);
+  inflateEnd(&stream);
+
+  EXPECT_EQ(src, decompressed);
+}
+
+// Fuzzer generated.
+static const uint8_t checkMatchCrashData[] = {
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
+    0x6e, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x01, 0x39, 0x6e, 0x6e,
+    0x00, 0x00, 0x00, 0x00, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e,
+    0x00, 0x00, 0x0a, 0x9a, 0x00, 0x00, 0x6e, 0x6e, 0x6e, 0x2a, 0x00, 0x00,
+    0x00, 0xd5, 0xf0, 0x00, 0x81, 0x02, 0xf3, 0xfd, 0xff, 0xab, 0xf3, 0x6e,
+    0x7e, 0x04, 0x5b, 0xf6, 0x2a, 0x2c, 0xf8, 0x00, 0x54, 0xf3, 0xa5, 0x0e,
+    0xfd, 0x6e, 0xff, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0xa4, 0x0b, 0xa5, 0x2a, 0x0d, 0x10, 0x01, 0x26, 0xf6, 0x04, 0x0e,
+    0xff, 0x6e, 0x6e, 0x6e, 0x76, 0x00, 0x00, 0x87, 0x01, 0xfe, 0x0d, 0xb6,
+    0x6e, 0x6e, 0xf7, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xfd, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x9b,
+    0x02, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
+    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x6e, 0xff, 0xff, 0x00,
+    0x00, 0xd5, 0xf0, 0x00, 0xff, 0x40, 0x7e, 0x0b, 0xa5, 0x10, 0x67, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x40, 0x7e, 0x0b, 0xa5, 0x10, 0x67,
+    0x7e, 0x32, 0x6e, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x40, 0x0b, 0xa5,
+    0x10, 0x67, 0x01, 0xfe, 0x0d, 0xb6, 0x2a, 0x00, 0x00, 0x58, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x6e, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x3d, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xd6, 0x2d, 0x2d, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
+    0x8a, 0x8a, 0x8a, 0x8a, 0x66, 0x8a, 0x8a, 0x8a, 0xee, 0x1d, 0x00, 0x00,
+    0x00, 0x02, 0x00, 0x00, 0x00, 0xee, 0x0a, 0x00, 0x00, 0x00, 0x54, 0x40,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x23, 0x7e, 0x00, 0x1e,
+    0x00, 0x00, 0xd5, 0xf0, 0x00, 0xff, 0x40, 0x0b, 0xa5, 0x10, 0x67, 0x01,
+    0xfe, 0x0d, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
+    0x8a, 0x8a, 0x8a, 0x2d, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0e,
+    0xfb, 0x00, 0x10, 0x24, 0x00, 0x00, 0xfb, 0xff, 0x00, 0x00, 0xff, 0x1f,
+    0xb3, 0x00, 0x04, 0x3d, 0x00, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
+    0x01, 0x45, 0x3d, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x11, 0x21, 0x00, 0x1e,
+    0x00, 0x0c, 0xb3, 0xfe, 0x0e, 0xee, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x6e, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6e, 0x00,
+    0x00, 0x87, 0x00, 0x33, 0x38, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x00, 0x00,
+    0x00, 0x38, 0x00, 0x00, 0xff, 0xff, 0xff, 0x04, 0x3f, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xff, 0x00, 0x31, 0x13, 0x13, 0x13,
+    0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0x30, 0x83, 0x33,
+    0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xff, 0x00, 0x01,
+    0x10, 0x0d, 0x2a, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x11,
+    0x21, 0x00, 0xa5, 0x00, 0x68, 0x68, 0x68, 0x67, 0x00, 0x00, 0xff, 0xff,
+    0x02, 0x00, 0x00, 0x68, 0x68, 0x68, 0x68, 0x00, 0x00, 0xfa, 0xff, 0xff,
+    0x03, 0x01, 0xff, 0x02, 0x00, 0x00, 0x68, 0x68, 0x68, 0x68, 0x0a, 0x10,
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+    0x06, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xfa, 0xff, 0xff, 0x08, 0xff, 0xff, 0xff, 0x00, 0x06, 0x04,
+    0x00, 0xf8, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+    0x00, 0xff, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x78, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0x00, 0x06, 0x04, 0x6e,
+    0x7e, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00,
+    0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x6e, 0x6e, 0x6e,
+    0x00, 0x01, 0x38, 0xd5, 0xf0, 0x00, 0x00, 0x2a, 0xfe, 0x04, 0x5b, 0x0d,
+    0xfd, 0x6e, 0x92, 0x28, 0xf9, 0xfb, 0xff, 0x07, 0xd2, 0xd6, 0x2d, 0x2d,
+    0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
+    0x8a, 0x8a, 0xc2, 0x91, 0x00, 0x5b, 0xef, 0xde, 0xf2, 0x6e, 0x6e, 0xfd,
+    0x0c, 0x02, 0x91, 0x62, 0x91, 0xfd, 0x6e, 0x6e, 0xd3, 0x06, 0x00, 0x00,
+    0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00,
+    0xd5, 0xf0, 0x00, 0xff, 0x00, 0x00, 0x31, 0x13, 0x13, 0x13, 0x04, 0x00,
+    0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x04, 0x00, 0x13, 0x0a, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x09, 0x00, 0x6a, 0x24, 0x26, 0x30, 0x01, 0x2e, 0x2a, 0xfe,
+    0x04, 0x5b, 0x0d, 0xfd, 0x6e, 0x6e, 0xd7, 0x06, 0x6e, 0x6e, 0x6e, 0x00,
+    0x00, 0xb1, 0xb1, 0xb1, 0xb1, 0x00, 0x00, 0x00, 0x6e, 0x5b, 0x00, 0x00,
+    0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x1e, 0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0b,
+    0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x24, 0x2a, 0x6e, 0x5c, 0x24,
+    0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x05, 0x00, 0x00, 0x00, 0x5d, 0x10, 0x6e, 0x6e, 0xa5, 0x2f, 0x00, 0x00,
+    0x95, 0x87, 0x00, 0x6e};
+
+TEST(ZlibTest, CheckMatchCrash) {
+  // See https://crbug.com/1113142.
+  z_stream stream;
+  stream.zalloc = nullptr;
+  stream.zfree = nullptr;
+
+  // Low windowbits to hit window sliding also with a relatively small input.
+  int ret = deflateInit2(&stream, /*comp level*/ 5, /*method*/ Z_DEFLATED,
+                         /*windowbits*/ -9, /*memlevel*/ 8,
+                         /*strategy*/ Z_DEFAULT_STRATEGY);
+  ASSERT_EQ(ret, Z_OK);
+
+  uint8_t compressed[sizeof(checkMatchCrashData) * 2];
+  stream.next_out = compressed;
+  stream.avail_out = sizeof(compressed);
+
+  for (size_t i = 0; i < sizeof(checkMatchCrashData); i++) {
+    ASSERT_GT(stream.avail_out, 0U);
+    stream.next_in = (uint8_t*)&checkMatchCrashData[i];
+    stream.avail_in = 1;
+    ret = deflate(&stream, Z_NO_FLUSH);
+    ASSERT_EQ(ret, Z_OK);
+  }
+
+  stream.next_in = nullptr;
+  stream.avail_in = 0;
+  ASSERT_GT(stream.avail_out, 0U);
+  ret = deflate(&stream, Z_FINISH);
+  ASSERT_EQ(ret, Z_STREAM_END);
+  size_t compressed_sz = sizeof(compressed) - stream.avail_out;
+  deflateEnd(&stream);
+
+  uint8_t decompressed[sizeof(checkMatchCrashData)];
+  ret = inflateInit2(&stream, -15);
+  ASSERT_EQ(ret, Z_OK);
+  stream.next_in = compressed;
+  stream.avail_in = compressed_sz;
+  stream.next_out = decompressed;
+  stream.avail_out = sizeof(decompressed);
+  ret = inflate(&stream, Z_FINISH);
+  ASSERT_EQ(ret, Z_STREAM_END);
+  inflateEnd(&stream);
+  ASSERT_EQ(
+      memcmp(checkMatchCrashData, decompressed, sizeof(checkMatchCrashData)),
+      0);
+}
diff --git a/deflate.c b/deflate.c
index e5a69dd..8bf93e5 100644
--- a/deflate.c
+++ b/deflate.c
@@ -60,6 +60,11 @@
 #include "crc32_simd.h"
 #endif
 
+#ifdef FASTEST
+/* See http://crbug.com/1113596 */
+#error "FASTEST is not supported in Chromium's zlib."
+#endif
+
 const char deflate_copyright[] =
    " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
 /*
@@ -1345,7 +1350,16 @@
          * 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]?");
+        if (!x86_cpu_enable_simd && !arm_cpu_enable_crc32) {
+          Assert(scan[2] == match[2], "scan[2]?");
+        } else {
+          /* 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 (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
@@ -1376,7 +1390,16 @@
          * the hash keys are equal and that HASH_BITS >= 8.
          */
         scan += 2, match++;
-        Assert(*scan == *match, "match[2]?");
+        if (!x86_cpu_enable_simd && !arm_cpu_enable_crc32) {
+          Assert(*scan == *match, "match[2]?");
+        } else {
+          /* 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 == *match || scan[1] != match[1], "match[2]??");
+        }
 
         /* We check for insufficient lookahead only every 8th comparison;
          * the 256th check will be made at strstart+258.
@@ -2037,7 +2060,13 @@
             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);
diff --git a/google/compression_utils.cc b/google/compression_utils.cc
index d6ee2b6..781c805 100644
--- a/google/compression_utils.cc
+++ b/google/compression_utils.cc
@@ -7,14 +7,13 @@
 #include "base/bit_cast.h"
 #include "base/check_op.h"
 #include "base/process/memory.h"
-#include "base/strings/string_piece.h"
 #include "base/sys_byteorder.h"
 
 #include "third_party/zlib/google/compression_utils_portable.h"
 
 namespace compression {
 
-bool GzipCompress(base::StringPiece input,
+bool GzipCompress(base::span<const char> input,
                   char* output_buffer,
                   size_t output_buffer_size,
                   size_t* compressed_size,
@@ -35,7 +34,11 @@
   return true;
 }
 
-bool GzipCompress(base::StringPiece input, std::string* output) {
+bool GzipCompress(base::span<const char> input, std::string* output) {
+  return GzipCompress(base::as_bytes(input), output);
+}
+
+bool GzipCompress(base::span<const uint8_t> input, std::string* output) {
   // Not using std::vector<> because allocation failures are recoverable,
   // which is hidden by std::vector<>.
   static_assert(sizeof(Bytef) == 1, "");
@@ -87,30 +90,44 @@
   return false;
 }
 
-bool GzipUncompress(base::StringPiece input, base::StringPiece output) {
+bool GzipUncompress(base::span<const char> input,
+                    base::span<const char> output) {
+  return GzipUncompress(base::as_bytes(input), base::as_bytes(output));
+}
+
+bool GzipUncompress(base::span<const uint8_t> input,
+                    base::span<const uint8_t> output) {
   uLongf uncompressed_size = GetUncompressedSize(input);
   if (uncompressed_size > output.size())
     return false;
   return zlib_internal::GzipUncompressHelper(
              bit_cast<Bytef*>(output.data()), &uncompressed_size,
              bit_cast<const Bytef*>(input.data()),
-             static_cast<uLongf>(input.length())) == Z_OK;
+             static_cast<uLongf>(input.size())) == Z_OK;
 }
 
-bool GzipUncompress(base::StringPiece input, std::string* output) {
+bool GzipUncompress(base::span<const char> input, std::string* output) {
+  return GzipUncompress(base::as_bytes(input), output);
+}
+
+bool GzipUncompress(base::span<const uint8_t> input, std::string* output) {
   // Disallow in-place usage, i.e., |input| using |*output| as underlying data.
-  DCHECK_NE(input.data(), output->data());
+  DCHECK_NE(reinterpret_cast<const char*>(input.data()), output->data());
   uLongf uncompressed_size = GetUncompressedSize(input);
   output->resize(uncompressed_size);
   return zlib_internal::GzipUncompressHelper(
              bit_cast<Bytef*>(output->data()), &uncompressed_size,
              bit_cast<const Bytef*>(input.data()),
-             static_cast<uLongf>(input.length())) == Z_OK;
+             static_cast<uLongf>(input.size())) == Z_OK;
 }
 
-uint32_t GetUncompressedSize(base::StringPiece compressed_data) {
+uint32_t GetUncompressedSize(base::span<const char> compressed_data) {
+  return GetUncompressedSize(base::as_bytes(compressed_data));
+}
+
+uint32_t GetUncompressedSize(base::span<const uint8_t> compressed_data) {
   return zlib_internal::GetGzipUncompressedSize(
-      bit_cast<Bytef*>(compressed_data.data()), compressed_data.length());
+      bit_cast<Bytef*>(compressed_data.data()), compressed_data.size());
 }
 
 }  // namespace compression
diff --git a/google/compression_utils.h b/google/compression_utils.h
index 5162207..cca47be 100644
--- a/google/compression_utils.h
+++ b/google/compression_utils.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "base/strings/string_piece.h"
+#include "base/containers/span.h"
 
 namespace compression {
 
@@ -18,7 +18,7 @@
 // |malloc_fn| and |free_fn| are pointers to malloc() and free()-like functions,
 // or nullptr to use the standard ones.
 // Returns true for success.
-bool GzipCompress(base::StringPiece input,
+bool GzipCompress(base::span<const char> input,
                   char* output_buffer,
                   size_t output_buffer_size,
                   size_t* compressed_size,
@@ -29,27 +29,41 @@
 // |input| and |output| are allowed to point to the same string (in-place
 // operation).
 // Returns true for success.
-bool GzipCompress(base::StringPiece input, std::string* output);
+bool GzipCompress(base::span<const char> input, std::string* output);
+
+// Like the above method, but using uint8_t instead.
+bool GzipCompress(base::span<const uint8_t> input, std::string* output);
 
 // Uncompresses the data in |input| using gzip, storing the result in |output|.
 // |input| and |output| are allowed to be the same string (in-place operation).
 // Returns true for success.
 bool GzipUncompress(const std::string& input, std::string* output);
 
-// Like the above method, but uses base::StringPiece to avoid allocations if
+// Like the above method, but uses base::span to avoid allocations if
 // needed. |output|'s size must be at least as large as the return value from
 // GetUncompressedSize.
 // Returns true for success.
-bool GzipUncompress(base::StringPiece input, base::StringPiece output);
+bool GzipUncompress(base::span<const char> input,
+                    base::span<const char> output);
+
+// Like the above method, but using uint8_t instead.
+bool GzipUncompress(base::span<const uint8_t> input,
+                    base::span<const uint8_t> output);
 
 // Uncompresses the data in |input| using gzip, and writes the results to
 // |output|, which must NOT be the underlying string of |input|, and is resized
 // if necessary.
 // Returns true for success.
-bool GzipUncompress(base::StringPiece input, std::string* output);
+bool GzipUncompress(base::span<const char> input, std::string* output);
+
+// Like the above method, but using uint8_t instead.
+bool GzipUncompress(base::span<const uint8_t> input, std::string* output);
 
 // Returns the uncompressed size from GZIP-compressed |compressed_data|.
-uint32_t GetUncompressedSize(base::StringPiece compressed_data);
+uint32_t GetUncompressedSize(base::span<const char> compressed_data);
+
+// Like the above method, but using uint8_t instead.
+uint32_t GetUncompressedSize(base::span<const uint8_t> compressed_data);
 
 }  // namespace compression
 
diff --git a/google/compression_utils_unittest.cc b/google/compression_utils_unittest.cc
index 398984b..31c3226 100644
--- a/google/compression_utils_unittest.cc
+++ b/google/compression_utils_unittest.cc
@@ -54,13 +54,9 @@
   EXPECT_EQ(golden_data, uncompressed_data);
 }
 
-TEST(CompressionUtilsTest, GzipUncompressionFromStringPieceToString) {
-  base::StringPiece compressed_data(
-      reinterpret_cast<const char*>(kCompressedData),
-      base::size(kCompressedData));
-
+TEST(CompressionUtilsTest, GzipUncompressionFromSpanToString) {
   std::string uncompressed_data;
-  EXPECT_TRUE(GzipUncompress(compressed_data, &uncompressed_data));
+  EXPECT_TRUE(GzipUncompress(kCompressedData, &uncompressed_data));
 
   std::string golden_data(reinterpret_cast<const char*>(kData),
                           base::size(kData));
diff --git a/patches/0006-fix-check_match.patch b/patches/0006-fix-check_match.patch
new file mode 100644
index 0000000..b21c363
--- /dev/null
+++ b/patches/0006-fix-check_match.patch
@@ -0,0 +1,42 @@
+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
+