Check that total compound dictionary size does not overflow. Thanks to @0xazanul who reported the problem in #1438 PiperOrigin-RevId: 896638456
diff --git a/c/common/platform.h b/c/common/platform.h index e1254d5..8080cbb 100644 --- a/c/common/platform.h +++ b/c/common/platform.h
@@ -24,6 +24,7 @@ #ifndef BROTLI_COMMON_PLATFORM_H_ #define BROTLI_COMMON_PLATFORM_H_ +#include <limits.h> #include <string.h> /* IWYU pragma: export memcmp, memcpy, memset */ #include <stdlib.h> /* IWYU pragma: export exit, free, malloc */ #include <sys/types.h> /* should include endian.h for us */ @@ -522,6 +523,14 @@ #define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B))) #define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B))) +static BROTLI_INLINE int brotli_safe_add_int(int a, int b, int* result) { + if (b > 0 && a > INT_MAX - b) return 0; + if (b < 0 && a < INT_MIN - b) return 0; + *result = a + b; + return 1; +} +#define BROTLI_SAFE_ADD(T, A, B, R) (brotli_safe_add_ ## T((A), (B), (R))) + #define BROTLI_SWAP(T, A, I, J) { \ T __brotli_swap_tmp = (A)[(I)]; \ (A)[(I)] = (A)[(J)]; \ @@ -607,6 +616,7 @@ BROTLI_UNUSED(&brotli_max_uint32_t); BROTLI_UNUSED(&brotli_min_uint8_t); BROTLI_UNUSED(&brotli_max_uint8_t); + BROTLI_UNUSED(&brotli_safe_add_int); BROTLI_UNUSED(&BrotliDefaultAllocFunc); BROTLI_UNUSED(&BrotliDefaultFreeFunc); BROTLI_UNUSED(&BrotliRotateRight16); @@ -615,6 +625,7 @@ #if BROTLI_ENABLE_DUMP BROTLI_UNUSED(&BrotliDump); #endif +} #if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && \ !defined(_M_ARM64EC) @@ -654,7 +665,6 @@ #elif defined(BROTLI_TZCNT64) #define BROTLI_MAX_SIMD_QUALITY 6 #endif -} #if defined(_MSC_VER) #define BROTLI_CRASH() __debugbreak(), (void)abort()
diff --git a/c/dec/decode.c b/c/dec/decode.c index 19c7e02..c4972a5 100644 --- a/c/dec/decode.c +++ b/c/dec/decode.c
@@ -1526,6 +1526,8 @@ static BROTLI_BOOL AttachCompoundDictionary( BrotliDecoderState* state, const uint8_t* data, size_t size) { BrotliDecoderCompoundDictionary* addon = state->compound_dictionary; + int new_size = (int)size; + if (new_size < 0 || (size_t)new_size != size) return BROTLI_FALSE; if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE; if (!addon) { addon = (BrotliDecoderCompoundDictionary*)BROTLI_DECODER_ALLOC( @@ -1540,10 +1542,13 @@ state->compound_dictionary = addon; } if (addon->num_chunks == 15) return BROTLI_FALSE; + if (!BROTLI_SAFE_ADD(int, addon->total_size, new_size, &new_size)) { + return BROTLI_FALSE; + } addon->chunks[addon->num_chunks] = data; addon->num_chunks++; - addon->total_size += (int)size; - addon->chunk_offsets[addon->num_chunks] = addon->total_size; + addon->total_size = new_size; + addon->chunk_offsets[addon->num_chunks] = new_size; return BROTLI_TRUE; }