Преглед на файлове

brotli: Sync with upstream commit ed1995b6b

https://github.com/google/brotli/commit/ed1995b6bda19244070ab5d331111f16f67c8054
Rémi Verschelde преди 2 години
родител
ревизия
7770e4447d

+ 3 - 2
thirdparty/README.md

@@ -47,12 +47,13 @@ fix build with our own copy of zstd (patch in `patches`).
 ## brotli
 
 - Upstream: https://github.com/google/brotli
-- Version: git (f4153a09f87cbb9c826d8fc12c74642bb2d879ea, 2022)
+- Version: git (ed1995b6bda19244070ab5d331111f16f67c8054, 2023)
 - License: MIT
 
 Files extracted from upstream source:
 
-- `common/`, `dec/` and `include/` folders
+- `common/`, `dec/` and `include/` folders from `c/`,
+  minus the `dictionary.bin*` files
 - `LICENSE`
 
 

+ 2 - 1
thirdparty/brotli/common/constants.h

@@ -12,10 +12,11 @@
 #ifndef BROTLI_COMMON_CONSTANTS_H_
 #define BROTLI_COMMON_CONSTANTS_H_
 
-#include "platform.h"
 #include <brotli/port.h>
 #include <brotli/types.h>
 
+#include "platform.h"
+
 /* Specification: 7.3. Encoding of the context map */
 #define BROTLI_CONTEXT_MAP_MAX_RLE 16
 

+ 1 - 1
thirdparty/brotli/common/dictionary.c

@@ -5897,7 +5897,7 @@ static BrotliDictionary kBrotliDictionary = {
 #endif
 };
 
-const BrotliDictionary* BrotliGetDictionary() {
+const BrotliDictionary* BrotliGetDictionary(void) {
   return &kBrotliDictionary;
 }
 

+ 2 - 1
thirdparty/brotli/common/platform.c

@@ -6,9 +6,10 @@
 
 #include <stdlib.h>
 
-#include "platform.h"
 #include <brotli/types.h>
 
+#include "platform.h"
+
 /* Default brotli_alloc_func */
 void* BrotliDefaultAllocFunc(void* opaque, size_t size) {
   BROTLI_UNUSED(opaque);

+ 36 - 87
thirdparty/brotli/common/platform.h

@@ -12,9 +12,9 @@
     * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations
     * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations
     * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations
-    * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
-      read and overlapping memcpy; this reduces decompression speed by 5%
     * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
+    * BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read
+      optimizations (mainly for testing purposes).
     * BROTLI_DEBUG dumps file name and line number when decoder detects stream
       or memory error
     * BROTLI_ENABLE_LOG enables asserts and dumps various state information
@@ -208,15 +208,19 @@ OR:
 #define BROTLI_TARGET_RISCV64
 #endif
 
+#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
+    defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
+#define BROTLI_TARGET_64_BITS 1
+#else
+#define BROTLI_TARGET_64_BITS 0
+#endif
+
 #if defined(BROTLI_BUILD_64_BIT)
 #define BROTLI_64_BITS 1
 #elif defined(BROTLI_BUILD_32_BIT)
 #define BROTLI_64_BITS 0
-#elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
-    defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
-#define BROTLI_64_BITS 1
 #else
-#define BROTLI_64_BITS 0
+#define BROTLI_64_BITS BROTLI_TARGET_64_BITS
 #endif
 
 #if (BROTLI_64_BITS)
@@ -260,18 +264,19 @@ OR:
 #undef BROTLI_X_BIG_ENDIAN
 #endif
 
-#if defined(BROTLI_BUILD_PORTABLE)
-#define BROTLI_ALIGNED_READ (!!1)
-#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
+#if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST)
+#define BROTLI_UNALIGNED_READ_FAST (!!0)
+#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) ||       \
     defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \
     defined(BROTLI_TARGET_RISCV64)
-/* Allow unaligned read only for white-listed CPUs. */
-#define BROTLI_ALIGNED_READ (!!0)
+/* These targets are known to generate efficient code for unaligned reads
+ * (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd
+ * together). */
+#define BROTLI_UNALIGNED_READ_FAST (!!1)
 #else
-#define BROTLI_ALIGNED_READ (!!1)
+#define BROTLI_UNALIGNED_READ_FAST (!!0)
 #endif
 
-#if BROTLI_ALIGNED_READ
 /* Portable unaligned memory access: read / write values via memcpy. */
 static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
   uint16_t t;
@@ -291,75 +296,6 @@ static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
 static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
   memcpy(p, &v, sizeof v);
 }
-#else  /* BROTLI_ALIGNED_READ */
-/* Unaligned memory access is allowed: just cast pointer to requested type. */
-#if BROTLI_SANITIZED
-/* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
-   AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
-   will miss a bug if 08 is the first unaddressable byte.
-   ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
-   miss a race between this access and some other accesses to 08.
-   MemorySanitizer will correctly propagate the shadow on unaligned stores
-   and correctly report bugs on unaligned loads, but it may not properly
-   update and report the origin of the uninitialized memory.
-   For all three tools, replacing an unaligned access with a tool-specific
-   callback solves the problem. */
-#if defined(__cplusplus)
-extern "C" {
-#endif  /* __cplusplus */
-  uint16_t __sanitizer_unaligned_load16(const void* p);
-  uint32_t __sanitizer_unaligned_load32(const void* p);
-  uint64_t __sanitizer_unaligned_load64(const void* p);
-  void __sanitizer_unaligned_store64(void* p, uint64_t v);
-#if defined(__cplusplus)
-}  /* extern "C" */
-#endif  /* __cplusplus */
-#define BrotliUnalignedRead16 __sanitizer_unaligned_load16
-#define BrotliUnalignedRead32 __sanitizer_unaligned_load32
-#define BrotliUnalignedRead64 __sanitizer_unaligned_load64
-#define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
-#else  /* BROTLI_SANITIZED */
-static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
-  return *(const uint16_t*)p;
-}
-static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {
-  return *(const uint32_t*)p;
-}
-#if (BROTLI_64_BITS)
-static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
-  return *(const uint64_t*)p;
-}
-static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
-  *(uint64_t*)p = v;
-}
-#else  /* BROTLI_64_BITS */
-/* Avoid emitting LDRD / STRD, which require properly aligned address. */
-/* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */
-
-#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
-typedef BROTLI_ALIGNED(1) uint64_t brotli_unaligned_uint64_t;
-
-static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
-  return (uint64_t) ((const brotli_unaligned_uint64_t*) p)[0];
-}
-static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
-  brotli_unaligned_uint64_t* dwords = (brotli_unaligned_uint64_t*) p;
-  dwords[0] = (brotli_unaligned_uint64_t) v;
-}
-#else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
-static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
-  uint64_t v;
-  memcpy(&v, p, sizeof(uint64_t));
-  return v;
-}
-
-static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
-  memcpy(p, &v, sizeof(uint64_t));
-}
-#endif  /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
-#endif  /* BROTLI_64_BITS */
-#endif  /* BROTLI_SANITIZED */
-#endif  /* BROTLI_ALIGNED_READ */
 
 #if BROTLI_LITTLE_ENDIAN
 /* Straight endianness. Just read / write values. */
@@ -435,6 +371,16 @@ static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
 }
 #endif  /* BROTLI_LITTLE_ENDIAN */
 
+static BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) {
+  void* v;
+  memcpy(&v, p, sizeof(void*));
+  return v;
+}
+
+static BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) {
+  memcpy(p, &v, sizeof(void*));
+}
+
 /* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */
 #if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \
     BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
@@ -467,6 +413,8 @@ static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
 #define BROTLI_DUMP() (void)(0)
 #endif
 
+/* BrotliRBit assumes brotli_reg_t fits native CPU register type. */
+#if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS)
 /* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */
 #if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \
     !defined(BROTLI_BUILD_NO_RBIT)
@@ -480,15 +428,14 @@ static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
 #define BROTLI_RBIT(x) BrotliRBit(x)
 #endif  /* armv7 / armv8 */
 #endif  /* gcc || clang */
+#endif  /* brotli_reg_t is native */
 #if !defined(BROTLI_RBIT)
 static BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ }
 #endif  /* BROTLI_RBIT */
 
-#define BROTLI_REPEAT(N, X) {     \
-  if ((N & 1) != 0) {X;}          \
-  if ((N & 2) != 0) {X; X;}       \
-  if ((N & 4) != 0) {X; X; X; X;} \
-}
+#define BROTLI_REPEAT_4(X) {X; X; X; X;}
+#define BROTLI_REPEAT_5(X) {X; X; X; X; X;}
+#define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;}
 
 #define BROTLI_UNUSED(X) (void)(X)
 
@@ -553,6 +500,8 @@ BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
   BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE);
   BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE);
   BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE);
+  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR);
+  BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR);
   BROTLI_UNUSED(&BrotliRBit);
   BROTLI_UNUSED(&brotli_min_double);
   BROTLI_UNUSED(&brotli_max_double);

+ 3 - 2
thirdparty/brotli/common/shared_dictionary_internal.h

@@ -9,11 +9,12 @@
 #ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
 #define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
 
-#include "dictionary.h"
 #include <brotli/shared_dictionary.h>
-#include "transform.h"
 #include <brotli/types.h>
 
+#include "dictionary.h"
+#include "transform.h"
+
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif

+ 3 - 2
thirdparty/brotli/dec/bit_reader.c

@@ -8,9 +8,10 @@
 
 #include "bit_reader.h"
 
-#include "../common/platform.h"
 #include <brotli/types.h>
 
+#include "../common/platform.h"
+
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
@@ -36,7 +37,7 @@ BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
   /* Fixing alignment after unaligned BrotliFillWindow would result accumulator
      overflow. If unalignment is caused by BrotliSafeReadBits, then there is
      enough space in accumulator to fix alignment. */
-  if (!BROTLI_ALIGNED_READ) {
+  if (BROTLI_UNALIGNED_READ_FAST) {
     aligned_read_mask = 0;
   }
   if (BrotliGetAvailableBits(br) == 0) {

+ 19 - 10
thirdparty/brotli/dec/bit_reader.h

@@ -11,9 +11,10 @@
 
 #include <string.h>  /* memcpy */
 
+#include <brotli/types.h>
+
 #include "../common/constants.h"
 #include "../common/platform.h"
-#include <brotli/types.h>
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
@@ -53,8 +54,8 @@ BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
 /* Ensures that accumulator is not empty.
    May consume up to sizeof(brotli_reg_t) - 1 bytes of input.
    Returns BROTLI_FALSE if data is required but there is no input available.
-   For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned
-   reading. */
+   For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for
+   aligned reading. */
 BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);
 
 /* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
@@ -107,7 +108,8 @@ static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(
 static BROTLI_INLINE void BrotliFillBitWindow(
     BrotliBitReader* const br, uint32_t n_bits) {
 #if (BROTLI_64_BITS)
-  if (!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 8)) {
+  if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
+      (n_bits <= 8)) {
     uint32_t bit_pos = br->bit_pos_;
     if (bit_pos >= 56) {
       br->val_ =
@@ -117,8 +119,8 @@ static BROTLI_INLINE void BrotliFillBitWindow(
       br->avail_in -= 7;
       br->next_in += 7;
     }
-  } else if (
-      !BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 16)) {
+  } else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
+             (n_bits <= 16)) {
     uint32_t bit_pos = br->bit_pos_;
     if (bit_pos >= 48) {
       br->val_ =
@@ -140,7 +142,8 @@ static BROTLI_INLINE void BrotliFillBitWindow(
     }
   }
 #else
-  if (!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 8)) {
+  if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&
+      (n_bits <= 8)) {
     uint32_t bit_pos = br->bit_pos_;
     if (bit_pos >= 24) {
       br->val_ =
@@ -338,6 +341,11 @@ static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
   return TO_BROTLI_BOOL(pad_bits == 0);
 }
 
+static BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {
+  br->avail_in -= num;
+  br->next_in += num;
+}
+
 /* Copies remaining input bytes stored in the bit reader to the output. Value
    |num| may not be larger than BrotliGetRemainingBytes. The bit reader must be
    warmed up again after this. */
@@ -349,9 +357,10 @@ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
     ++dest;
     --num;
   }
-  memcpy(dest, br->next_in, num);
-  br->avail_in -= num;
-  br->next_in += num;
+  if (num > 0) {
+    memcpy(dest, br->next_in, num);
+    BrotliDropBytes(br, num);
+  }
 }
 
 #if defined(__cplusplus) || defined(c_plusplus)

+ 83 - 20
thirdparty/brotli/dec/decode.c

@@ -113,8 +113,9 @@ void BrotliDecoderDestroyInstance(BrotliDecoderState* state) {
 
 /* Saves error code and converts it to BrotliDecoderResult. */
 static BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(
-    BrotliDecoderState* s, BrotliDecoderErrorCode e) {
+    BrotliDecoderState* s, BrotliDecoderErrorCode e, size_t consumed_input) {
   s->error_code = (int)e;
+  s->used_input += consumed_input;
   switch (e) {
     case BROTLI_DECODER_SUCCESS:
       return BROTLI_DECODER_RESULT_SUCCESS;
@@ -1172,7 +1173,7 @@ static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(
     size_t sample = s->context_map[offset];
     size_t j;
     for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS);) {
-      BROTLI_REPEAT(4, error |= s->context_map[offset + j++] ^ sample;)
+      BROTLI_REPEAT_4({ error |= s->context_map[offset + j++] ^ sample; })
     }
     if (error == 0) {
       s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);
@@ -1353,6 +1354,57 @@ static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
   return BROTLI_TRUE;
 }
 
+static BrotliDecoderErrorCode BROTLI_NOINLINE
+SkipMetadataBlock(BrotliDecoderState* s) {
+  BrotliBitReader* br = &s->br;
+
+  if (s->meta_block_remaining_len == 0) {
+    return BROTLI_DECODER_SUCCESS;
+  }
+
+  BROTLI_DCHECK((BrotliGetAvailableBits(br) & 7) == 0);
+
+  /* Drain accumulator. */
+  if (BrotliGetAvailableBits(br) >= 8) {
+    uint8_t buffer[8];
+    int nbytes = (int)(BrotliGetAvailableBits(br)) >> 3;
+    BROTLI_DCHECK(nbytes <= 8);
+    if (nbytes > s->meta_block_remaining_len) {
+      nbytes = s->meta_block_remaining_len;
+    }
+    BrotliCopyBytes(buffer, br, (size_t)nbytes);
+    if (s->metadata_chunk_func) {
+      s->metadata_chunk_func(s->metadata_callback_opaque, buffer,
+                             (size_t)nbytes);
+    }
+    s->meta_block_remaining_len -= nbytes;
+    if (s->meta_block_remaining_len == 0) {
+      return BROTLI_DECODER_SUCCESS;
+    }
+  }
+
+  /* Direct access to metadata is possible. */
+  int nbytes = (int)BrotliGetRemainingBytes(br);
+  if (nbytes > s->meta_block_remaining_len) {
+    nbytes = s->meta_block_remaining_len;
+  }
+  if (nbytes > 0) {
+    if (s->metadata_chunk_func) {
+      s->metadata_chunk_func(s->metadata_callback_opaque, br->next_in,
+                             (size_t)nbytes);
+    }
+    BrotliDropBytes(br, (size_t)nbytes);
+    s->meta_block_remaining_len -= nbytes;
+    if (s->meta_block_remaining_len == 0) {
+      return BROTLI_DECODER_SUCCESS;
+    }
+  }
+
+  BROTLI_DCHECK(BrotliGetRemainingBytes(br) == 0);
+
+  return BROTLI_DECODER_NEEDS_MORE_INPUT;
+}
+
 static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
     size_t* available_out, uint8_t** next_out, size_t* total_out,
     BrotliDecoderState* s) {
@@ -2243,6 +2295,9 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
     size_t* available_out, uint8_t** next_out, size_t* total_out) {
   BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
   BrotliBitReader* br = &s->br;
+  size_t input_size = *available_in;
+#define BROTLI_SAVE_ERROR_CODE(code) \
+    SaveErrorCode(s, (code), input_size - *available_in)
   /* Ensure that |total_out| is set, even if no data will ever be pushed out. */
   if (total_out) {
     *total_out = s->partial_pos_out;
@@ -2252,8 +2307,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
     return BROTLI_DECODER_RESULT_ERROR;
   }
   if (*available_out && (!next_out || !*next_out)) {
-    return SaveErrorCode(
-        s, BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));
+    return BROTLI_SAVE_ERROR_CODE(
+        BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));
   }
   if (!*available_out) next_out = 0;
   if (s->buffer_length == 0) {  /* Just connect bit reader to input stream. */
@@ -2410,6 +2465,10 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
         }
         if (s->is_metadata) {
           s->state = BROTLI_STATE_METADATA;
+          if (s->metadata_start_func) {
+            s->metadata_start_func(s->metadata_callback_opaque,
+                                   (size_t)s->meta_block_remaining_len);
+          }
           break;
         }
         if (s->meta_block_remaining_len == 0) {
@@ -2502,17 +2561,11 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
       }
 
       case BROTLI_STATE_METADATA:
-        for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
-          uint32_t bits;
-          /* Read one byte and ignore it. */
-          if (!BrotliSafeReadBits(br, 8, &bits)) {
-            result = BROTLI_DECODER_NEEDS_MORE_INPUT;
-            break;
-          }
-        }
-        if (result == BROTLI_DECODER_SUCCESS) {
-          s->state = BROTLI_STATE_METABLOCK_DONE;
+        result = SkipMetadataBlock(s);
+        if (result != BROTLI_DECODER_SUCCESS) {
+          break;
         }
+        s->state = BROTLI_STATE_METABLOCK_DONE;
         break;
 
       case BROTLI_STATE_METABLOCK_HEADER_2: {
@@ -2586,7 +2639,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
             s, &s->distance_hgroup, distance_alphabet_size_max,
             distance_alphabet_size_limit, s->num_dist_htrees);
         if (!allocation_success) {
-          return SaveErrorCode(s,
+          return BROTLI_SAVE_ERROR_CODE(
               BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));
         }
         s->loop_counter = 0;
@@ -2600,7 +2653,7 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
           case 0: hgroup = &s->literal_hgroup; break;
           case 1: hgroup = &s->insert_copy_hgroup; break;
           case 2: hgroup = &s->distance_hgroup; break;
-          default: return SaveErrorCode(s, BROTLI_FAILURE(
+          default: return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(
               BROTLI_DECODER_ERROR_UNREACHABLE));  /* COV_NF_LINE */
         }
         result = HuffmanTreeGroupDecode(hgroup, s);
@@ -2710,10 +2763,11 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
             break;
           }
         }
-        return SaveErrorCode(s, result);
+        return BROTLI_SAVE_ERROR_CODE(result);
     }
   }
-  return SaveErrorCode(s, result);
+  return BROTLI_SAVE_ERROR_CODE(result);
+#undef BROTLI_SAVE_ERROR_CODE
 }
 
 BROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState* s) {
@@ -2743,7 +2797,7 @@ const uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {
   } else {
     /* ... or stream is broken. Normally this should be caught by
        BrotliDecoderDecompressStream, this is just a safeguard. */
-    if ((int)status < 0) SaveErrorCode(s, status);
+    if ((int)status < 0) SaveErrorCode(s, status, 0);
     *size = 0;
     result = 0;
   }
@@ -2776,10 +2830,19 @@ const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c) {
   }
 }
 
-uint32_t BrotliDecoderVersion() {
+uint32_t BrotliDecoderVersion(void) {
   return BROTLI_VERSION;
 }
 
+void BrotliDecoderSetMetadataCallbacks(
+    BrotliDecoderState* state,
+    brotli_decoder_metadata_start_func start_func,
+    brotli_decoder_metadata_chunk_func chunk_func, void* opaque) {
+  state->metadata_start_func = start_func;
+  state->metadata_chunk_func = chunk_func;
+  state->metadata_callback_opaque = opaque;
+}
+
 /* Escalate internal functions visibility; for testing purposes only. */
 #if defined(BROTLI_TEST)
 BROTLI_BOOL SafeReadSymbolForTest(

+ 6 - 3
thirdparty/brotli/dec/huffman.c

@@ -10,9 +10,10 @@
 
 #include <string.h>  /* memcpy, memset */
 
+#include <brotli/types.h>
+
 #include "../common/constants.h"
 #include "../common/platform.h"
-#include <brotli/types.h>
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
@@ -117,11 +118,13 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
   int bits_count;
   BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <=
                 BROTLI_REVERSE_BITS_MAX);
+  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5);
 
   /* Generate offsets into sorted symbol table by code length. */
   symbol = -1;
   bits = 1;
-  BROTLI_REPEAT(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH, {
+  /* BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5 */
+  BROTLI_REPEAT_5({
     symbol += count[bits];
     offset[bits] = symbol;
     bits++;
@@ -132,7 +135,7 @@ void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
   /* Sort symbols by length, by symbol order within each length. */
   symbol = BROTLI_CODE_LENGTH_CODES;
   do {
-    BROTLI_REPEAT(6, {
+    BROTLI_REPEAT_6({
       symbol--;
       sorted[offset[code_lengths[symbol]]--] = symbol;
     });

+ 2 - 1
thirdparty/brotli/dec/huffman.h

@@ -9,9 +9,10 @@
 #ifndef BROTLI_DEC_HUFFMAN_H_
 #define BROTLI_DEC_HUFFMAN_H_
 
-#include "../common/platform.h"
 #include <brotli/types.h>
 
+#include "../common/platform.h"
+
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif

+ 2 - 1
thirdparty/brotli/dec/prefix.h

@@ -10,9 +10,10 @@
 #ifndef BROTLI_DEC_PREFIX_H_
 #define BROTLI_DEC_PREFIX_H_
 
-#include "../common/constants.h"
 #include <brotli/types.h>
 
+#include "../common/constants.h"
+
 typedef struct CmdLutElement {
   uint8_t insert_len_extra_bits;
   uint8_t copy_len_extra_bits;

+ 19 - 1
thirdparty/brotli/dec/state.c

@@ -8,8 +8,9 @@
 
 #include <stdlib.h>  /* free, malloc */
 
-#include "../common/dictionary.h"
 #include <brotli/types.h>
+
+#include "../common/dictionary.h"
 #include "huffman.h"
 
 #if defined(__cplusplus) || defined(c_plusplus)
@@ -43,6 +44,7 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
   s->pos = 0;
   s->rb_roundtrips = 0;
   s->partial_pos_out = 0;
+  s->used_input = 0;
 
   s->block_type_trees = NULL;
   s->block_len_trees = NULL;
@@ -87,6 +89,10 @@ BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
       BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);
   if (!s->dictionary) return BROTLI_FALSE;
 
+  s->metadata_start_func = NULL;
+  s->metadata_chunk_func = NULL;
+  s->metadata_callback_opaque = 0;
+
   return BROTLI_TRUE;
 }
 
@@ -129,9 +135,21 @@ void BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) {
   BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees);
 }
 
+#ifdef BROTLI_REPORTING
+/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */
+void BrotliDecoderOnFinish(const BrotliDecoderState* s);
+#define BROTLI_DECODER_ON_FINISH(s) BrotliDecoderOnFinish(s);
+#else
+#if !defined(BROTLI_DECODER_ON_FINISH)
+#define BROTLI_DECODER_ON_FINISH(s) (void)(s);
+#endif
+#endif
+
 void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
   BrotliDecoderStateCleanupAfterMetablock(s);
 
+  BROTLI_DECODER_ON_FINISH(s);
+
   BROTLI_DECODER_FREE(s, s->compound_dictionary);
   BrotliSharedDictionaryDestroyInstance(s->dictionary);
   s->dictionary = NULL;

+ 11 - 2
thirdparty/brotli/dec/state.h

@@ -9,12 +9,14 @@
 #ifndef BROTLI_DEC_STATE_H_
 #define BROTLI_DEC_STATE_H_
 
+#include <brotli/decode.h>
+#include <brotli/shared_dictionary.h>
+#include <brotli/types.h>
+
 #include "../common/constants.h"
 #include "../common/dictionary.h"
 #include "../common/platform.h"
-#include <brotli/shared_dictionary.h>
 #include "../common/transform.h"
-#include <brotli/types.h>
 #include "bit_reader.h"
 #include "huffman.h"
 
@@ -321,6 +323,13 @@ struct BrotliDecoderStateStruct {
 
   /* Less used attributes are at the end of this struct. */
 
+  brotli_decoder_metadata_start_func metadata_start_func;
+  brotli_decoder_metadata_chunk_func metadata_chunk_func;
+  void* metadata_callback_opaque;
+
+  /* For reporting. */
+  uint64_t used_input;  /* how many bytes of input are consumed */
+
   /* States inside function calls. */
   BrotliRunningMetablockHeaderState substate_metablock_header;
   BrotliRunningUncompressedState substate_uncompressed;

+ 41 - 0
thirdparty/brotli/include/brotli/decode.h

@@ -361,6 +361,47 @@ BROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);
  */
 BROTLI_DEC_API uint32_t BrotliDecoderVersion(void);
 
+/**
+ * Callback to fire on metadata block start.
+ *
+ * After this callback is fired, if @p size is not @c 0, it is followed by
+ * ::brotli_decoder_metadata_chunk_func as more metadata block contents become
+ * accessible.
+ *
+ * @param opaque callback handle
+ * @param size size of metadata block
+ */
+typedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size);
+
+/**
+ * Callback to fire on metadata block chunk becomes available.
+ *
+ * This function can be invoked multiple times per metadata block; block should
+ * be considered finished when sum of @p size matches the announced metadata
+ * block size. Chunks contents pointed by @p data are transient and shouln not
+ * be accessed after leaving the callback.
+ *
+ * @param opaque callback handle
+ * @param data pointer to metadata contents
+ * @param size size of metadata block chunk, at least @c 1
+ */
+typedef void (*brotli_decoder_metadata_chunk_func)(void* opaque,
+                                                   const uint8_t* data,
+                                                   size_t size);
+
+/**
+ * Sets callback for receiving metadata blocks.
+ *
+ * @param state decoder instance
+ * @param start_func callback on metadata block start
+ * @param chunk_func callback on metadata block chunk
+ * @param opaque callback handle
+ */
+BROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks(
+    BrotliDecoderState* state,
+    brotli_decoder_metadata_start_func start_func,
+    brotli_decoder_metadata_chunk_func chunk_func, void* opaque);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 } /* extern "C" */
 #endif

+ 1 - 1
thirdparty/brotli/include/brotli/encode.h

@@ -453,7 +453,7 @@ BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(
  *
  * This method is used to make language bindings easier and more efficient:
  *  -# push data to ::BrotliEncoderCompressStream,
- *     until ::BrotliEncoderHasMoreOutput returns BROTL_TRUE
+ *     until ::BrotliEncoderHasMoreOutput returns BROTLI_TRUE
  *  -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific
  *     entity
  *

+ 0 - 8
thirdparty/brotli/include/brotli/port.h

@@ -224,14 +224,6 @@
 #define BROTLI_HAS_FEATURE(feature) (0)
 #endif
 
-#if defined(ADDRESS_SANITIZER) || BROTLI_HAS_FEATURE(address_sanitizer) || \
-    defined(THREAD_SANITIZER) || BROTLI_HAS_FEATURE(thread_sanitizer) ||   \
-    defined(MEMORY_SANITIZER) || BROTLI_HAS_FEATURE(memory_sanitizer)
-#define BROTLI_SANITIZED 1
-#else
-#define BROTLI_SANITIZED 0
-#endif
-
 #if defined(_WIN32) || defined(__CYGWIN__)
 #define BROTLI_PUBLIC
 #elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) ||                         \