Merge "Upgrade zlib to f4f46747bd5c68320126fea54d6993ae0b5c3edd" am: 32db2895d2
am: 763b7acb29

Change-Id: I92425781c685da0938852e750b74c30e8daacca8
diff --git a/METADATA b/METADATA
index a6e3a4e..1458d13 100644
--- a/METADATA
+++ b/METADATA
@@ -5,11 +5,11 @@
     type: GIT
     value: "https://chromium.googlesource.com/chromium/src/third_party/zlib/"
   }
-  version: "ddebad26cfadeb4ecdfe3da8beb396a85cf90c91"
+  version: "f4f46747bd5c68320126fea54d6993ae0b5c3edd"
   license_type: NOTICE
   last_upgrade_date {
     year: 2019
-    month: 10
-    day: 9
+    month: 11
+    day: 8
   }
 }
diff --git a/chromeconf.h b/chromeconf.h
index e9aa386..666093d 100644
--- a/chromeconf.h
+++ b/chromeconf.h
@@ -13,7 +13,7 @@
 #define ZEXTERN __declspec(dllimport)
 #endif
 #elif defined(ZLIB_IMPLEMENTATION)
-#define ZEXPORT __attribute__((visibility("default")))
+#define ZEXTERN __attribute__((visibility("default")))
 #endif
 #endif
 
diff --git a/google/compression_utils.cc b/google/compression_utils.cc
index 6af42f3..9f63a84 100644
--- a/google/compression_utils.cc
+++ b/google/compression_utils.cc
@@ -42,7 +42,7 @@
   const uLongf input_size = static_cast<uLongf>(input.size());
 
   uLongf compressed_data_size =
-      zlib_internal::GZipExpectedCompressedSize(input_size);
+      zlib_internal::GzipExpectedCompressedSize(input_size);
 
   Bytef* compressed_data;
   if (!base::UncheckedMalloc(compressed_data_size,
@@ -109,14 +109,8 @@
 }
 
 uint32_t GetUncompressedSize(base::StringPiece compressed_data) {
-  // The uncompressed size is stored in the last 4 bytes of |input| in LE.
-  uint32_t size;
-  if (compressed_data.length() < sizeof(size))
-    return 0;
-  memcpy(&size,
-         &compressed_data.data()[compressed_data.length() - sizeof(size)],
-         sizeof(size));
-  return base::ByteSwapToLE32(size);
+  return zlib_internal::GetGzipUncompressedSize(
+      bit_cast<Bytef*>(compressed_data.data()), compressed_data.length());
 }
 
 }  // namespace compression
diff --git a/google/compression_utils_portable.cc b/google/compression_utils_portable.cc
index 686b657..21338b5 100644
--- a/google/compression_utils_portable.cc
+++ b/google/compression_utils_portable.cc
@@ -8,7 +8,6 @@
 #include "third_party/zlib/google/compression_utils_portable.h"
 
 #include <stddef.h>
-#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -29,19 +28,58 @@
 // The expected compressed size is based on the input size factored by
 // internal Zlib constants (e.g. window size, etc) plus the wrapper
 // header size.
-uLongf GZipExpectedCompressedSize(uLongf input_size) {
+uLongf GzipExpectedCompressedSize(uLongf input_size) {
   return kGzipZlibHeaderDifferenceBytes + compressBound(input_size);
 }
 
-// This code is taken almost verbatim from third_party/zlib/compress.c. The only
-// difference is deflateInit2() is called which sets the window bits to be > 16.
-// That causes a gzip header to be emitted rather than a zlib header.
+// The expected decompressed size is stored in the last
+// 4 bytes of |input| in LE. See https://tools.ietf.org/html/rfc1952#page-5
+uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length) {
+  uint32_t size;
+  if (length < sizeof(size))
+    return 0;
+
+  memcpy(&size, &compressed_data[length - sizeof(size)], sizeof(size));
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+  return size;
+#else
+  return __builtin_bswap32(size);
+#endif
+}
+
+// The number of window bits determines the type of wrapper to use - see
+// https://cs.chromium.org/chromium/src/third_party/zlib/zlib.h?l=566
+inline int ZlibStreamWrapperType(WrapperType type) {
+  if (type == ZLIB)  // zlib DEFLATE stream wrapper
+    return MAX_WBITS;
+  if (type == GZIP)  // gzip DEFLATE stream wrapper
+    return MAX_WBITS + kWindowBitsToGetGzipHeader;
+  if (type == ZRAW)  // no wrapper, use raw DEFLATE
+    return -MAX_WBITS;
+  return 0;
+}
+
 int GzipCompressHelper(Bytef* dest,
                        uLongf* dest_length,
                        const Bytef* source,
                        uLong source_length,
                        void* (*malloc_fn)(size_t),
                        void (*free_fn)(void*)) {
+  return CompressHelper(GZIP, dest, dest_length, source, source_length,
+                        malloc_fn, free_fn);
+}
+
+// This code is taken almost verbatim from third_party/zlib/compress.c. The only
+// difference is deflateInit2() is called which allows different window bits to
+// be set. > 16 causes a gzip header to be emitted rather than a zlib header,
+// and negative causes no header to emitted.
+int CompressHelper(WrapperType wrapper_type,
+                   Bytef* dest,
+                   uLongf* dest_length,
+                   const Bytef* source,
+                   uLong source_length,
+                   void* (*malloc_fn)(size_t),
+                   void (*free_fn)(void*)) {
   z_stream stream;
 
   // FIXME(cavalcantii): z_const is not defined as 'const'.
@@ -80,17 +118,21 @@
     stream.opaque = static_cast<voidpf>(0);
   }
 
-  gz_header gzip_header;
-  memset(&gzip_header, 0, sizeof(gzip_header));
   int err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
-                         MAX_WBITS + kWindowBitsToGetGzipHeader,
-                         kZlibMemoryLevel, Z_DEFAULT_STRATEGY);
+                         ZlibStreamWrapperType(wrapper_type), kZlibMemoryLevel,
+                         Z_DEFAULT_STRATEGY);
   if (err != Z_OK)
     return err;
 
-  err = deflateSetHeader(&stream, &gzip_header);
-  if (err != Z_OK)
-    return err;
+  // This has to exist outside of the if statement to prevent it going off the
+  // stack before deflate(), which will use this object.
+  gz_header gzip_header;
+  if (wrapper_type == GZIP) {
+    memset(&gzip_header, 0, sizeof(gzip_header));
+    err = deflateSetHeader(&stream, &gzip_header);
+    if (err != Z_OK)
+      return err;
+  }
 
   err = deflate(&stream, Z_FINISH);
   if (err != Z_STREAM_END) {
@@ -103,13 +145,22 @@
   return err;
 }
 
-// This code is taken almost verbatim from third_party/zlib/uncompr.c. The only
-// difference is inflateInit2() is called which sets the window bits to be > 16.
-// That causes a gzip header to be parsed rather than a zlib header.
 int GzipUncompressHelper(Bytef* dest,
                          uLongf* dest_length,
                          const Bytef* source,
                          uLong source_length) {
+  return UncompressHelper(GZIP, dest, dest_length, source, source_length);
+}
+
+// This code is taken almost verbatim from third_party/zlib/uncompr.c. The only
+// difference is inflateInit2() is called which allows different window bits to
+// be set. > 16 causes a gzip header to be emitted rather than a zlib header,
+// and negative causes no header to emitted.
+int UncompressHelper(WrapperType wrapper_type,
+                     Bytef* dest,
+                     uLongf* dest_length,
+                     const Bytef* source,
+                     uLong source_length) {
   z_stream stream;
 
   // FIXME(cavalcantii): z_const is not defined as 'const'.
@@ -126,7 +177,7 @@
   stream.zalloc = static_cast<alloc_func>(0);
   stream.zfree = static_cast<free_func>(0);
 
-  int err = inflateInit2(&stream, MAX_WBITS + kWindowBitsToGetGzipHeader);
+  int err = inflateInit2(&stream, ZlibStreamWrapperType(wrapper_type));
   if (err != Z_OK)
     return err;
 
diff --git a/google/compression_utils_portable.h b/google/compression_utils_portable.h
index 5c07521..7c3753b 100644
--- a/google/compression_utils_portable.h
+++ b/google/compression_utils_portable.h
@@ -7,6 +7,8 @@
 #ifndef THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_
 #define THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_
 
+#include <stdint.h>
+
 #if defined(USE_SYSTEM_ZLIB)
 #include <zlib.h>
 #else
@@ -15,7 +17,15 @@
 
 namespace zlib_internal {
 
-uLongf GZipExpectedCompressedSize(uLongf input_size);
+enum WrapperType {
+  ZLIB,
+  GZIP,
+  ZRAW,
+};
+
+uLongf GzipExpectedCompressedSize(uLongf input_size);
+
+uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length);
 
 int GzipCompressHelper(Bytef* dest,
                        uLongf* dest_length,
@@ -24,10 +34,25 @@
                        void* (*malloc_fn)(size_t),
                        void (*free_fn)(void*));
 
+int CompressHelper(WrapperType wrapper_type,
+                   Bytef* dest,
+                   uLongf* dest_length,
+                   const Bytef* source,
+                   uLong source_length,
+                   void* (*malloc_fn)(size_t),
+                   void (*free_fn)(void*));
+
 int GzipUncompressHelper(Bytef* dest,
                          uLongf* dest_length,
                          const Bytef* source,
                          uLong source_length);
+
+int UncompressHelper(WrapperType wrapper_type,
+                     Bytef* dest,
+                     uLongf* dest_length,
+                     const Bytef* source,
+                     uLong source_length);
+
 }  // namespace zlib_internal
 
 #endif  // THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_