diff --git a/c/dec/state.c b/c/dec/state.c index dcf61b9eb..34149634f 100644 --- a/c/dec/state.c +++ b/c/dec/state.c @@ -167,7 +167,17 @@ BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s, This number is discovered "unlimited" "enough" calculator; it is actually a wee bigger than required in several cases (especially for alphabets with less than 16 symbols). */ + /* alphabet_size_limit is the largest alphabet handled by the decoder. + The biggest is the distance alphabet: + BROTLI_NUM_DISTANCE_SYMBOLS == 1128 per RFC 7932. + max_table_size = alphabet_size_limit + 376 is therefore bounded by + 1128 + 376 == 1504. */ const size_t max_table_size = alphabet_size_limit + 376; + /* ntrees is the number of huffman trees in the group (one per block + type). RFC 7932 caps the number of block types at 256 + (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES), so ntrees < 1024 (i.e. + ntrees <= 1023) leaves comfortable margin. The same invariant + covers the htree_size multiplication below. */ const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size; const size_t htree_size = sizeof(HuffmanCode*) * ntrees; /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */ diff --git a/c/enc/block_encoder_inc.h b/c/enc/block_encoder_inc.h index 8cbd5eac6..3dedc7dc3 100644 --- a/c/enc/block_encoder_inc.h +++ b/c/enc/block_encoder_inc.h @@ -15,6 +15,10 @@ static void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self, const HistogramType* histograms, const size_t histograms_size, const size_t alphabet_size, HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) { + /* histograms_size is the number of block types + (<= 257; RFC 7932 caps the number of block types at 256 plus one + entry for the implicit type). histogram_length_ is the alphabet + size, the largest of which is BROTLI_NUM_COMMAND_SYMBOLS == 704. */ const size_t table_size = histograms_size * self->histogram_length_; self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size); self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size); diff --git a/c/enc/block_splitter.c b/c/enc/block_splitter.c index 13e924f09..9911a8450 100644 --- a/c/enc/block_splitter.c +++ b/c/enc/block_splitter.c @@ -57,6 +57,8 @@ static void CopyLiteralsToByteArray(const Command* cmds, size_t i; for (i = 0; i < num_commands; ++i) { size_t insert_len = cmds[i].insert_len_; + /* Both insert_len and from_pos are bounded by meta-block length + (<= 16 MiB per RFC 7932), so from_pos + insert_len cannot wrap. */ if (from_pos + insert_len > mask) { size_t head_size = mask + 1 - from_pos; memcpy(literals + pos, data + from_pos, head_size); diff --git a/c/enc/block_splitter_inc.h b/c/enc/block_splitter_inc.h index 5e34cb9c9..cbb5b03a1 100644 --- a/c/enc/block_splitter_inc.h +++ b/c/enc/block_splitter_inc.h @@ -205,6 +205,8 @@ static void FN(ClusterBlocks)(MemoryManager* m, const size_t num_blocks, uint8_t* block_ids, BlockSplit* split) { + /* num_blocks is bounded by meta-block length, which RFC 7932 caps at + 16 MiB. */ uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks); uint32_t* u32 = BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH); @@ -451,6 +453,13 @@ static void FN(SplitByteVector)(MemoryManager* m, uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length); size_t num_blocks = 0; const size_t bitmaplen = (num_histograms + 7) >> 3; + /* data_size is the alphabet size; the largest alphabet that reaches + SplitByteVector is BROTLI_NUM_COMMAND_SYMBOLS == 704. + num_histograms is capped by the encoder's sampling heuristics + (kMaxLiteralHistograms == 100, kMaxCommandHistograms == 50; + see block_splitter.c). + bitmaplen = (num_histograms + 7) >> 3, so it is capped at 13. + length is meta-block length (<= 16 MiB per RFC 7932). */ double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms); double* cost = BROTLI_ALLOC(m, double, num_histograms); uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen);