diff options
author | eustas <eustas@chromium.org> | 2015-11-07 15:43:06 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-11-07 23:43:58 +0000 |
commit | f9a29fdb5041606057668f7a900f6c08ae6d51cb (patch) | |
tree | e0464c5cbde49bbf29451ac1c9e8371c69603250 | |
parent | 67b3cb5374eb47fd6c20924b37141bf9ea5e79d2 (diff) | |
download | chromium_src-f9a29fdb5041606057668f7a900f6c08ae6d51cb.zip chromium_src-f9a29fdb5041606057668f7a900f6c08ae6d51cb.tar.gz chromium_src-f9a29fdb5041606057668f7a900f6c08ae6d51cb.tar.bz2 |
Update brotli from 8e90bf4c5f6479353beb83af4118782621947765 (Oct 5 2015) to c90ec29f54e9165df815b0f1311cfddb1be4afad (Nov 7 2015)
BUG=472009
Review URL: https://codereview.chromium.org/1411573011
Cr-Commit-Position: refs/heads/master@{#358538}
-rw-r--r-- | third_party/brotli/README.chromium | 2 | ||||
-rw-r--r-- | third_party/brotli/dec/bit_reader.c | 21 | ||||
-rw-r--r-- | third_party/brotli/dec/bit_reader.h | 236 | ||||
-rw-r--r-- | third_party/brotli/dec/decode.c | 2130 | ||||
-rw-r--r-- | third_party/brotli/dec/decode.h | 17 | ||||
-rw-r--r-- | third_party/brotli/dec/huffman.c | 1 | ||||
-rw-r--r-- | third_party/brotli/dec/port.h | 83 | ||||
-rw-r--r-- | third_party/brotli/dec/prefix.h | 2 | ||||
-rw-r--r-- | third_party/brotli/dec/state.c | 46 | ||||
-rw-r--r-- | third_party/brotli/dec/state.h | 68 | ||||
-rw-r--r-- | third_party/brotli/dec/streams.c | 2 | ||||
-rw-r--r-- | third_party/brotli/dec/streams.h | 2 | ||||
-rw-r--r-- | third_party/brotli/dec/types.h | 16 |
13 files changed, 1676 insertions, 950 deletions
diff --git a/third_party/brotli/README.chromium b/third_party/brotli/README.chromium index c57d2f2..972cdb3 100644 --- a/third_party/brotli/README.chromium +++ b/third_party/brotli/README.chromium @@ -1,6 +1,6 @@ Name: Brotli URL: https://github.com/google/brotli -Version: 8e90bf4c5f6479353beb83af4118782621947765 +Version: c90ec29f54e9165df815b0f1311cfddb1be4afad License: Apache 2.0 License File: LICENSE Security Critical: yes diff --git a/third_party/brotli/dec/bit_reader.c b/third_party/brotli/dec/bit_reader.c index 351cbc2..ddd014e 100644 --- a/third_party/brotli/dec/bit_reader.c +++ b/third_party/brotli/dec/bit_reader.c @@ -24,15 +24,9 @@ extern "C" { #endif -void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input) { - BROTLI_DCHECK(br != NULL); - - br->input_ = input; +void BrotliInitBitReader(BrotliBitReader* const br) { br->val_ = 0; br->bit_pos_ = sizeof(br->val_) << 3; - br->avail_in = 0; - br->eos_ = 0; - br->next_in = br->buf_; } int BrotliWarmupBitReader(BrotliBitReader* const br) { @@ -43,12 +37,17 @@ int BrotliWarmupBitReader(BrotliBitReader* const br) { if (!BROTLI_ALIGNED_READ) { aligned_read_mask = 0; } - while (br->bit_pos_ == (sizeof(br->val_) << 3) || - (((size_t)br->next_in) & aligned_read_mask) != 0) { - if (!br->avail_in) { + if (BrotliGetAvailableBits(br) == 0) { + if (!BrotliPullByte(br)) { return 0; } - BrotliPullByte(br); + } + + while ((((size_t)br->next_in) & aligned_read_mask) != 0) { + if (!BrotliPullByte(br)) { + /* If we consumed all the input, we don't care about the alignment. */ + return 1; + } } return 1; } diff --git a/third_party/brotli/dec/bit_reader.h b/third_party/brotli/dec/bit_reader.h index f25fd4a..f390348 100644 --- a/third_party/brotli/dec/bit_reader.h +++ b/third_party/brotli/dec/bit_reader.h @@ -20,45 +20,57 @@ #include <string.h> #include "./port.h" -#include "./streams.h" #include "./types.h" #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif -#define BROTLI_READ_SIZE 1024 -/* 128 bytes, plus 8 bytes slack for valid 128-byte BrotliCheckInputAmount with - some bytes read in val_ of bit reader. */ -#define BROTLI_IMPLICIT_ZEROES 136 -#define BROTLI_IBUF_SIZE (BROTLI_READ_SIZE + BROTLI_IMPLICIT_ZEROES) -#define BROTLI_IBUF_MASK (BROTLI_READ_SIZE - 1) +#if (BROTLI_64_BITS) +#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 4 +typedef uint64_t reg_t; +#else +#define BROTLI_SHORT_FILL_BIT_WINDOW_READ 2 +typedef uint32_t reg_t; +#endif + +static const uint32_t kBitMask[33] = { 0x0000, + 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, + 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, + 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, + 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, + 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, + 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF +}; -/* Masking with this expression turns to a single "Unsigned Bit Field Extract" - UBFX instruction on ARM. */ static BROTLI_INLINE uint32_t BitMask(uint32_t n) { + if (IS_CONSTANT(n) || BROTLI_HAS_UBFX) { + /* Masking with this expression turns to a single + "Unsigned Bit Field Extract" UBFX instruction on ARM. */ return ~((0xffffffffU) << n); + } else { + return kBitMask[n]; + } } typedef struct { -#if (BROTLI_64_BITS) - uint64_t val_; /* pre-fetched bits */ -#else - uint32_t val_; /* pre-fetched bits */ -#endif + reg_t val_; /* pre-fetched bits */ uint32_t bit_pos_; /* current bit-reading position in val_ */ - uint8_t* next_in; /* the byte we're reading from */ - uint32_t avail_in; - int eos_; /* input stream is finished */ - BrotliInput input_; /* input callback */ - - /* Input byte buffer, consist of a ringbuffer and a "slack" region where */ - /* bytes from the start of the ringbuffer are copied. */ - uint8_t buf_[BROTLI_IBUF_SIZE]; + const uint8_t* next_in; /* the byte we're reading from */ + size_t avail_in; } BrotliBitReader; +typedef struct { + reg_t val_; + uint32_t bit_pos_; + const uint8_t* next_in; + size_t avail_in; +} BrotliBitReaderState; + /* Initializes the bitreader fields. */ -void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input); +void BrotliInitBitReader(BrotliBitReader* const br); /* Ensures that accumulator is not empty. May consume one byte of input. Returns 0 if data is required but there is no input available. @@ -66,66 +78,35 @@ void BrotliInitBitReader(BrotliBitReader* const br, BrotliInput input); reading. */ int BrotliWarmupBitReader(BrotliBitReader* const br); -/* Pulls data from the input to the the read buffer. +static BROTLI_INLINE void BrotliBitReaderSaveState( + BrotliBitReader* const from, BrotliBitReaderState* to) { + to->val_ = from->val_; + to->bit_pos_ = from->bit_pos_; + to->next_in = from->next_in; + to->avail_in = from->avail_in; +} - Returns 0 if one of: - - the input callback returned an error, or - - there is no more input and the position is past the end of the stream. - - finish is false and less than BROTLI_READ_SIZE are available - a next call - when more data is available makes it continue including the partially read - data +static BROTLI_INLINE void BrotliBitReaderRestoreState( + BrotliBitReader* const to, BrotliBitReaderState* from) { + to->val_ = from->val_; + to->bit_pos_ = from->bit_pos_; + to->next_in = from->next_in; + to->avail_in = from->avail_in; +} - If finish is true and the end of the stream is reached, - BROTLI_IMPLICIT_ZEROES additional zero bytes are copied to the ringbuffer. -*/ -static BROTLI_INLINE int BrotliReadInput( - BrotliBitReader* const br, int finish) { - if (PREDICT_FALSE(br->eos_)) { - return 0; - } else { - size_t i; - int bytes_read; - if (br->next_in != br->buf_) { - for (i = 0; i < br->avail_in; i++) { - br->buf_[i] = br->next_in[i]; - } - br->next_in = br->buf_; - } - bytes_read = BrotliRead(br->input_, br->next_in + br->avail_in, - (size_t)(BROTLI_READ_SIZE - br->avail_in)); - if (bytes_read < 0) { - return 0; - } - br->avail_in += (uint32_t)bytes_read; - if (br->avail_in < BROTLI_READ_SIZE) { - if (!finish) { - return 0; - } - br->eos_ = 1; - /* Store BROTLI_IMPLICIT_ZEROES bytes of zero after the stream end. */ - memset(br->next_in + br->avail_in, 0, BROTLI_IMPLICIT_ZEROES); - br->avail_in += BROTLI_IMPLICIT_ZEROES; - } - return 1; - } +static BROTLI_INLINE uint32_t BrotliGetAvailableBits( + const BrotliBitReader* br) { + return (BROTLI_64_BITS ? 64 : 32) - br->bit_pos_; } /* Returns amount of unread bytes the bit reader still has buffered from the BrotliInput, including whole bytes in br->val_. */ static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) { - size_t result = br->avail_in + sizeof(br->val_) - (br->bit_pos_ >> 3); - if (!br->eos_) { - return result; - } - if (result <= BROTLI_IMPLICIT_ZEROES) { - return 0; - } - return result - BROTLI_IMPLICIT_ZEROES; + return br->avail_in + (BrotliGetAvailableBits(br) >> 3); } /* Checks if there is at least num bytes left in the input ringbuffer (excluding - the bits remaining in br->val_). The maximum value for num is - BROTLI_IMPLICIT_ZEROES bytes. */ + the bits remaining in br->val_). */ static BROTLI_INLINE int BrotliCheckInputAmount( BrotliBitReader* const br, size_t num) { return br->avail_in >= num; @@ -160,6 +141,7 @@ static BROTLI_INLINE uint32_t BrotliLoad32LE(const uint8_t* in) { } } +#if (BROTLI_64_BITS) static BROTLI_INLINE uint64_t BrotliLoad64LE(const uint8_t* in) { if (BROTLI_LITTLE_ENDIAN) { return *((const uint64_t*)in); @@ -186,6 +168,7 @@ static BROTLI_INLINE uint64_t BrotliLoad64LE(const uint8_t* in) { return value; } } +#endif /* Guarantees that there are at least n_bits + 1 bits in accumulator. Precondition: accumulator contains at least 1 bit. @@ -215,8 +198,8 @@ static BROTLI_INLINE void BrotliFillBitWindow( br->val_ >>= 32; br->bit_pos_ ^= 32; /* here same as -= 32 because of the if condition */ br->val_ |= ((uint64_t)BrotliLoad32LE(br->next_in)) << 32; - br->avail_in -= 4; - br->next_in += 4; + br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ; + br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ; } } #else @@ -233,15 +216,24 @@ static BROTLI_INLINE void BrotliFillBitWindow( br->val_ >>= 16; br->bit_pos_ ^= 16; /* here same as -= 16 because of the if condition */ br->val_ |= ((uint32_t)BrotliLoad16LE(br->next_in)) << 16; - br->avail_in -= 2; - br->next_in += 2; + br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ; + br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ; } } #endif } +/* Mosltly like BrotliFillBitWindow, but guarantees only 16 bits and reads no + more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */ +static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) { + BrotliFillBitWindow(br, 17); +} + /* Pulls one byte of input to accumulator. */ -static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br) { +static BROTLI_INLINE int BrotliPullByte(BrotliBitReader* const br) { + if (br->avail_in == 0) { + return 0; + } br->val_ >>= 8; #if (BROTLI_64_BITS) br->val_ |= ((uint64_t)*br->next_in) << 56; @@ -251,39 +243,68 @@ static BROTLI_INLINE void BrotliPullByte(BrotliBitReader* const br) { br->bit_pos_ -= 8; --br->avail_in; ++br->next_in; + return 1; } -/* Like BrotliGetBits, but does not mask the result, it is only guaranteed -that it has minimum n_bits. */ -static BROTLI_INLINE uint32_t BrotliGetBitsUnmasked( - BrotliBitReader* const br, uint32_t n_bits) { - BrotliFillBitWindow(br, n_bits); - return (uint32_t)(br->val_ >> br->bit_pos_); +/* Returns currently available bits. + The number of valid bits could be calclulated by BrotliGetAvailableBits. */ +static BROTLI_INLINE reg_t BrotliGetBitsUnmasked(BrotliBitReader* const br) { + return br->val_ >> br->bit_pos_; +} + +/* Like BrotliGetBits, but does not mask the result. + The result contains at least 16 valid bits. */ +static BROTLI_INLINE uint32_t BrotliGet16BitsUnmasked( + BrotliBitReader* const br) { + BrotliFillBitWindow(br, 16); + return (uint32_t)BrotliGetBitsUnmasked(br); } /* Returns the specified number of bits from br without advancing bit pos. */ static BROTLI_INLINE uint32_t BrotliGetBits( BrotliBitReader* const br, uint32_t n_bits) { BrotliFillBitWindow(br, n_bits); - return (uint32_t)(br->val_ >> br->bit_pos_) & BitMask(n_bits); + return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits); +} + +/* Tries to peek the specified amount of bits. Returns 0, if there is not + enough input. */ +static BROTLI_INLINE int BrotliSafeGetBits( + BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { + return 0; + } + } + *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits); + return 1; } /* Advances the bit pos by n_bits. */ static BROTLI_INLINE void BrotliDropBits( - BrotliBitReader* const br, int n_bits) { - br->bit_pos_ += (uint32_t)n_bits; + BrotliBitReader* const br, uint32_t n_bits) { + br->bit_pos_ += n_bits; +} + +static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) { + uint32_t unused_bytes = BrotliGetAvailableBits(br) >> 3; + uint32_t unused_bits = unused_bytes << 3; + br->avail_in += unused_bytes; + br->next_in -= unused_bytes; + br->val_ <<= unused_bits; + br->bit_pos_ += unused_bits; } /* Reads the specified number of bits from br and advances the bit pos. Precondition: accumulator MUST contain at least n_bits. */ static BROTLI_INLINE void BrotliTakeBits( BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { - *val = (uint32_t)(br->val_ >> br->bit_pos_) & BitMask(n_bits); + *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits); #ifdef BROTLI_DECODE_DEBUG printf("[BrotliReadBits] %d %d %d val: %6x\n", (int)br->avail_in, (int)br->bit_pos_, n_bits, (int)*val); #endif - br->bit_pos_ += n_bits; + BrotliDropBits(br, n_bits); } /* Reads the specified number of bits from br and advances the bit pos. @@ -307,14 +328,13 @@ static BROTLI_INLINE uint32_t BrotliReadBits( } /* Tries to read the specified amount of bits. Returns 0, if there is not - enough input. */ + enough input. n_bits MUST be positive. */ static BROTLI_INLINE int BrotliSafeReadBits( BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { - while (br->bit_pos_ + (uint32_t)n_bits > (sizeof(br->val_) << 3)) { - if (br->avail_in == 0) { + while (BrotliGetAvailableBits(br) < n_bits) { + if (!BrotliPullByte(br)) { return 0; } - BrotliPullByte(br); } BrotliTakeBits(br, n_bits, val); return 1; @@ -323,7 +343,7 @@ static BROTLI_INLINE int BrotliSafeReadBits( /* Advances the bit reader position to the next byte boundary and verifies that any skipped bits are set to zero. */ static BROTLI_INLINE int BrotliJumpToByteBoundary(BrotliBitReader* br) { - uint32_t pad_bits_count = (64 - (int)br->bit_pos_) & 0x7; + uint32_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7; uint32_t pad_bits = 0; if (pad_bits_count != 0) { BrotliTakeBits(br, pad_bits_count, &pad_bits); @@ -335,12 +355,13 @@ static BROTLI_INLINE int BrotliJumpToByteBoundary(BrotliBitReader* br) { Precondition: bit reader is parked to a byte boundary. Returns -1 if operation is not feasible. */ static BROTLI_INLINE int BrotliPeekByte(BrotliBitReader* br, size_t offset) { - size_t bytes_left = sizeof(br->val_) - (br->bit_pos_ >> 3); - if (br->bit_pos_ & 7) { + uint32_t available_bits = BrotliGetAvailableBits(br); + size_t bytes_left = available_bits >> 3; + if (available_bits & 7) { return -1; } if (offset < bytes_left) { - return (br->val_ >> (br->bit_pos_ + (unsigned)(offset << 3))) & 0xFF; + return (BrotliGetBitsUnmasked(br) >> (unsigned)(offset << 3)) & 0xFF; } offset -= bytes_left; if (offset < br->avail_in) { @@ -354,30 +375,17 @@ static BROTLI_INLINE int BrotliPeekByte(BrotliBitReader* br, size_t offset) { warmed up again after this. */ static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest, BrotliBitReader* br, size_t num) { - while (br->bit_pos_ + 8 <= (BROTLI_64_BITS ? 64 : 32) - && num > 0) { - *dest = (uint8_t)(br->val_ >> br->bit_pos_); - br->bit_pos_ += 8; + while (BrotliGetAvailableBits(br) >= 8 && num > 0) { + *dest = (uint8_t)BrotliGetBitsUnmasked(br); + BrotliDropBits(br, 8); ++dest; --num; } memcpy(dest, br->next_in, num); - br->avail_in -= (uint32_t)num; + br->avail_in -= num; br->next_in += num; } -/* Checks that bit reader hasn't read after the end of input. - Returns 0 if bit reader has used implicit zeroes after the end of input. */ -static BROTLI_INLINE int BrotliIsBitReaderOK(BrotliBitReader* br) { - size_t remaining_bytes = - br->avail_in + sizeof(br->val_) - (br->bit_pos_ >> 3); - return !br->eos_ || (remaining_bytes >= BROTLI_IMPLICIT_ZEROES); -} - -#undef BROTLI_IMPLICIT_ZEROES -#undef BROTLI_IBUF_SIZE -#undef BROTLI_IBUF_MASK - #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif diff --git a/third_party/brotli/dec/decode.c b/third_party/brotli/dec/decode.c index eb91ce3..bd0d213 100644 --- a/third_party/brotli/dec/decode.c +++ b/third_party/brotli/dec/decode.c @@ -46,8 +46,8 @@ extern "C" { #define BROTLI_LOG(x) #endif -static const uint8_t kDefaultCodeLength = 8; -static const uint8_t kCodeLengthRepeatCode = 16; +static const uint32_t kDefaultCodeLength = 8; +static const uint32_t kCodeLengthRepeatCode = 16; static const uint32_t kNumLiteralCodes = 256; static const uint32_t kNumInsertAndCopyCodes = 704; static const uint32_t kNumBlockLengthCodes = 26; @@ -274,27 +274,94 @@ static BrotliResult BROTLI_NOINLINE DecodeMetaBlockLength(BrotliState* s, } } -/* Decodes the next Huffman code from bit-stream. Reads 0 - 15 bits. */ -static BROTLI_INLINE uint32_t ReadSymbol(const HuffmanCode* table, - BrotliBitReader* br) { - /* Read the bits for two reads at once. */ - uint32_t val = BrotliGetBitsUnmasked(br, 15); - table += val & HUFFMAN_TABLE_MASK; +/* Decodes the Huffman code. + This method doesn't read data from the bit reader, BUT drops the amount of + bits that correspond to the decoded symbol. + bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */ +static BROTLI_INLINE uint32_t DecodeSymbol(uint32_t bits, + const HuffmanCode* table, + BrotliBitReader* br) { + table += bits & HUFFMAN_TABLE_MASK; if (table->bits > HUFFMAN_TABLE_BITS) { uint32_t nbits = table->bits - HUFFMAN_TABLE_BITS; BrotliDropBits(br, HUFFMAN_TABLE_BITS); table += table->value; - table += (val >> HUFFMAN_TABLE_BITS) & BitMask(nbits); + table += (bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits); } BrotliDropBits(br, table->bits); return table->value; } +/* Reads and decodes the next Huffman code from bit-stream. + This method peeks 16 bits of input and drops 0 - 15 of them. */ +static BROTLI_INLINE uint32_t ReadSymbol(const HuffmanCode* table, + BrotliBitReader* br) { + return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br); +} + +/* Same as DecodeSymbol, but it is known that there is less than 15 bits of + input are currently available. */ +static BROTLI_NOINLINE int SafeDecodeSymbol(const HuffmanCode* table, + BrotliBitReader* br, + uint32_t* result) { + uint32_t val; + uint32_t available_bits = BrotliGetAvailableBits(br); + if (available_bits == 0) { + if (table->bits == 0) { + *result = table->value; + return 1; + } + return 0; /* No valid bits at all. */ + } + val = (uint32_t)BrotliGetBitsUnmasked(br); + table += val & HUFFMAN_TABLE_MASK; + if (table->bits <= HUFFMAN_TABLE_BITS) { + if (table->bits <= available_bits) { + BrotliDropBits(br, table->bits); + *result = table->value; + return 1; + } else { + return 0; /* Not enough bits for the first level. */ + } + } + if (available_bits <= HUFFMAN_TABLE_BITS) { + return 0; /* Not enough bits to move to the second level. */ + } + + /* Speculatively drop HUFFMAN_TABLE_BITS. */ + val = (val & BitMask(table->bits)) >> HUFFMAN_TABLE_BITS; + available_bits -= HUFFMAN_TABLE_BITS; + table += table->value + val; + if (available_bits < table->bits) { + return 0; /* Not enough bits for the second level. */ + } + + BrotliDropBits(br, HUFFMAN_TABLE_BITS + table->bits); + *result = table->value; + return 1; +} + +static BROTLI_INLINE int SafeReadSymbol(const HuffmanCode* table, + BrotliBitReader* br, + uint32_t* result) { + uint32_t val; + if (PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) { + *result = DecodeSymbol(val, table, br); + return 1; + } + return SafeDecodeSymbol(table, br, result); +} + + /* Makes a look-up in first level Huffman table. Peeks 8 bits. */ -static BROTLI_INLINE void PreloadSymbol(const HuffmanCode* table, +static BROTLI_INLINE void PreloadSymbol(int safe, + const HuffmanCode* table, BrotliBitReader* br, uint32_t* bits, uint32_t* value) { + if (safe) { + return; + } table += BrotliGetBits(br, HUFFMAN_TABLE_BITS); *bits = table->bits; *value = table->value; @@ -308,7 +375,7 @@ static BROTLI_INLINE uint32_t ReadPreloadedSymbol(const HuffmanCode* table, uint32_t* value) { uint32_t result = *value; if (PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) { - uint32_t val = BrotliGetBitsUnmasked(br, 15); + uint32_t val = BrotliGet16BitsUnmasked(br); const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value; uint32_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS)); BrotliDropBits(br, HUFFMAN_TABLE_BITS); @@ -316,9 +383,9 @@ static BROTLI_INLINE uint32_t ReadPreloadedSymbol(const HuffmanCode* table, BrotliDropBits(br, ext->bits); result = ext->value; } else { - BrotliDropBits(br, (int)*bits); + BrotliDropBits(br, *bits); } - PreloadSymbol(table, br, bits, value); + PreloadSymbol(0, table, br, bits, value); return result; } @@ -331,6 +398,250 @@ static BROTLI_INLINE uint32_t Log2Floor(uint32_t x) { return result; } +/* Reads (s->symbol + 1) symbols. + Totally 1..4 symbols are read, 1..10 bits each. + The list of symbols MUST NOT contain duplicates. + */ +static BrotliResult ReadSimpleHuffmanSymbols(uint32_t alphabet_size, + BrotliState* s) { + /* max_bits == 1..10; symbol == 0..3; 1..40 bits will be read. */ + BrotliBitReader* br = &s->br; + uint32_t max_bits = Log2Floor(alphabet_size - 1); + uint32_t i = s->sub_loop_counter; + uint32_t num_symbols = s->symbol; + while (i <= num_symbols) { + uint32_t v; + if (PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) { + s->sub_loop_counter = i; + s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + if (v >= alphabet_size) { + return BROTLI_FAILURE(); + } + s->symbols_lists_array[i] = (uint16_t)v; + BROTLI_LOG_UINT(s->symbols_lists_array[i]); + ++i; + } + + for (i = 0; i < num_symbols; ++i) { + uint32_t k = i + 1; + for (; k <= num_symbols; ++k) { + if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) { + return BROTLI_FAILURE(); + } + } + } + + return BROTLI_RESULT_SUCCESS; +} + +/* Process single decoded symbol code length: + A) reset the repeat variable + B) remember code length (if it is not 0) + C) extend corredponding index-chain + D) reduce the huffman space + E) update the histogram + */ +static BROTLI_INLINE void ProcessSingleCodeLength(uint32_t code_len, + uint32_t* symbol, uint32_t* repeat, uint32_t* space, + uint32_t* prev_code_len, uint16_t* symbol_lists, + uint16_t* code_length_histo, int* next_symbol) { + *repeat = 0; + if (code_len != 0) { /* code_len == 1..15 */ + symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol); + next_symbol[code_len] = (int)(*symbol); + *prev_code_len = code_len; + *space -= 32768U >> code_len; + code_length_histo[code_len]++; + } + (*symbol)++; +} + +/* Process repeated symbol code length. + A) Check if it is the extension of previous repeat sequence; if the decoded + value is not kCodeLengthRepeatCode, then it is a new symbol-skip + B) Update repeat variable + C) Check if operation is feasible (fits alphapet) + D) For each symbol do the same operations as in ProcessSingleCodeLength + + PRECONDITION: code_len == kCodeLengthRepeatCode or kCodeLengthRepeatCode + 1 + */ +static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len, + uint32_t repeat_delta, uint32_t alphabet_size, uint32_t* symbol, + uint32_t* repeat, uint32_t* space, uint32_t* prev_code_len, + uint32_t* repeat_code_len, uint16_t* symbol_lists, + uint16_t* code_length_histo, int* next_symbol) { + uint32_t old_repeat; + uint32_t new_len = 0; + if (code_len == kCodeLengthRepeatCode) { + new_len = *prev_code_len; + } + if (*repeat_code_len != new_len) { + *repeat = 0; + *repeat_code_len = new_len; + } + old_repeat = *repeat; + if (*repeat > 0) { + *repeat -= 2; + *repeat <<= code_len - 14U; + } + *repeat += repeat_delta + 3U; + repeat_delta = *repeat - old_repeat; + if (*symbol + repeat_delta > alphabet_size) { + (void)BROTLI_FAILURE(); + *symbol = alphabet_size; + *space = 0xFFFFF; + return; + } + if (*repeat_code_len != 0) { + unsigned last = *symbol + repeat_delta; + int next = next_symbol[*repeat_code_len]; + do { + symbol_lists[next] = (uint16_t)*symbol; + next = (int)*symbol; + } while (++(*symbol) != last); + next_symbol[*repeat_code_len] = next; + *space -= repeat_delta << (15 - *repeat_code_len); + code_length_histo[*repeat_code_len] = (uint16_t) + (code_length_histo[*repeat_code_len] + repeat_delta); + } else { + *symbol += repeat_delta; + } +} + +/* Reads and decodes symbol codelengths. */ +static BrotliResult ReadSymbolCodeLengths( + uint32_t alphabet_size, BrotliState* s) { + BrotliBitReader* br = &s->br; + uint32_t symbol = s->symbol; + uint32_t repeat = s->repeat; + uint32_t space = s->space; + uint32_t prev_code_len = s->prev_code_len; + uint32_t repeat_code_len = s->repeat_code_len; + uint16_t* symbol_lists = s->symbol_lists; + uint16_t* code_length_histo = s->code_length_histo; + int* next_symbol = s->next_symbol; + if (!BrotliWarmupBitReader(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + while (symbol < alphabet_size && space > 0) { + const HuffmanCode* p = s->table; + uint32_t code_len; + if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) { + s->symbol = symbol; + s->repeat = repeat; + s->prev_code_len = prev_code_len; + s->repeat_code_len = repeat_code_len; + s->space = space; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + BrotliFillBitWindow16(br); + p += BrotliGetBitsUnmasked(br) & + BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); + BrotliDropBits(br, p->bits); /* Use 1..5 bits */ + code_len = p->value; /* code_len == 0..17 */ + if (code_len < kCodeLengthRepeatCode) { + ProcessSingleCodeLength(code_len, &symbol, &repeat, &space, + &prev_code_len, symbol_lists, code_length_histo, next_symbol); + } else { /* code_len == 16..17, extra_bits == 2..3 */ + uint32_t repeat_delta = + (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(code_len - 14U); + BrotliDropBits(br, code_len - 14U); + ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size, + &symbol, &repeat, &space, &prev_code_len, &repeat_code_len, + symbol_lists, code_length_histo, next_symbol); + } + } + s->space = space; + return BROTLI_RESULT_SUCCESS; +} + +static BrotliResult SafeReadSymbolCodeLengths( + uint32_t alphabet_size, BrotliState* s) { + BrotliBitReader* br = &s->br; + while (s->symbol < alphabet_size && s->space > 0) { + const HuffmanCode* p = s->table; + uint32_t code_len; + uint32_t bits = 0; + uint32_t available_bits = BrotliGetAvailableBits(br); + if (available_bits != 0) { + bits = (uint32_t)BrotliGetBitsUnmasked(br); + } + p += bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); + if (p->bits > available_bits) goto pullMoreInput; + code_len = p->value; /* code_len == 0..17 */ + if (code_len < kCodeLengthRepeatCode) { + BrotliDropBits(br, p->bits); + ProcessSingleCodeLength(code_len, &s->symbol, &s->repeat, &s->space, + &s->prev_code_len, s->symbol_lists, s->code_length_histo, + s->next_symbol); + } else { /* code_len == 16..17, extra_bits == 2..3 */ + uint32_t extra_bits = code_len - 14U; + uint32_t repeat_delta = (bits >> p->bits) & BitMask(extra_bits); + if (available_bits < p->bits + extra_bits) goto pullMoreInput; + BrotliDropBits(br, p->bits + extra_bits); + ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size, + &s->symbol, &s->repeat, &s->space, &s->prev_code_len, + &s->repeat_code_len, s->symbol_lists, s->code_length_histo, + s->next_symbol); + } + continue; + +pullMoreInput: + if (!BrotliPullByte(br)) { + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + } + return BROTLI_RESULT_SUCCESS; +} + +/* Reads and decodes 15..18 codes using static prefix code. + Each code is 2..4 bits long. In total 30..72 bits are used. */ +static BrotliResult ReadCodeLengthCodeLengths(BrotliState* s) { + BrotliBitReader* br = &s->br; + uint32_t num_codes = s->repeat; + unsigned space = s->space; + uint32_t i = s->sub_loop_counter; + for (; i < CODE_LENGTH_CODES; ++i) { + const uint8_t code_len_idx = kCodeLengthCodeOrder[i]; + uint32_t ix; + uint32_t v; + if (PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) { + uint32_t available_bits = BrotliGetAvailableBits(br); + if (available_bits != 0) { + ix = BrotliGetBitsUnmasked(br) & 0xF; + } else { + ix = 0; + } + if (kCodeLengthPrefixLength[ix] > available_bits) { + s->sub_loop_counter = i; + s->repeat = num_codes; + s->space = space; + s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + } + v = kCodeLengthPrefixValue[ix]; + BrotliDropBits(br, kCodeLengthPrefixLength[ix]); + s->code_length_code_lengths[code_len_idx] = (uint8_t)v; + BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx); + if (v != 0) { + space = space - (32U >> v); + ++num_codes; + ++s->code_length_histo[v]; + if (space - 1U >= 32U) { + /* space is 0 or wrapped around */ + break; + } + } + } + if (!(num_codes == 1 || space == 0)) { + return BROTLI_FAILURE(); + } + return BROTLI_RESULT_SUCCESS; +} + /* Decodes the Huffman tables. There are 2 scenarios: A) Huffman code contains only few symbols (1..4). Those symbols are read @@ -348,84 +659,71 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_size, uint32_t* opt_table_size, BrotliState* s) { BrotliBitReader* br = &s->br; - uint32_t i; /* Unnecessary masking, but might be good for safety. */ alphabet_size &= 0x3ff; /* State machine */ switch (s->substate_huffman) { case BROTLI_STATE_HUFFMAN_NONE: - if (!BrotliCheckInputAmount(br, 32)) { + if (!BrotliSafeReadBits(br, 2, &s->sub_loop_counter)) { return BROTLI_RESULT_NEEDS_MORE_INPUT; } - i = BrotliReadBits(br, 2); + BROTLI_LOG_UINT(s->sub_loop_counter); /* The value is used as follows: 1 for simple code; 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */ - BROTLI_LOG_UINT(i); - if (i == 1) { - /* Read symbols, codes & code lengths directly. */ - uint32_t max_bits = Log2Floor(alphabet_size - 1); - uint32_t num_symbols = BrotliReadBits(br, 2); - for (i = 0; i < 4; ++i) { - s->symbols_lists_array[i] = 0; - } - i = 0; - /* max_bits == 0..10; symbol == 0..3; 0..40 bits will be read. */ - do { - uint32_t v = BrotliReadBits(br, max_bits); - if (v >= alphabet_size) { - return BROTLI_FAILURE(); - } - s->symbols_lists_array[i] = (uint16_t)v; - BROTLI_LOG_UINT(s->symbols_lists_array[i]); - } while (++i <= num_symbols); - for (i = 0; i < num_symbols; ++i) { - uint32_t k = i + 1; - for (; k <= num_symbols; ++k) { - if (s->symbols_lists_array[i] == s->symbols_lists_array[k]) { - return BROTLI_FAILURE(); - } - } - } - if (num_symbols == 3) { - num_symbols += BrotliReadBits(br, 1); - } - BROTLI_LOG_UINT(num_symbols); - i = BrotliBuildSimpleHuffmanTable( - table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, num_symbols); - if (opt_table_size) { - *opt_table_size = i; - } - s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; - return BROTLI_RESULT_SUCCESS; - } else { /* Decode Huffman-coded code lengths. */ - int8_t num_codes = 0; - unsigned space = 32; + if (s->sub_loop_counter != 1) { + s->space = 32; + s->repeat = 0; /* num_codes */ memset(&s->code_length_histo[0], 0, sizeof(s->code_length_histo[0]) * (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1)); memset(&s->code_length_code_lengths[0], 0, - sizeof(s->code_length_code_lengths)); - /* 15..18 codes will be read, 2..4 bits each; 30..72 bits totally. */ - for (; i < CODE_LENGTH_CODES; ++i) { - const uint8_t code_len_idx = kCodeLengthCodeOrder[i]; - uint8_t ix = (uint8_t)BrotliGetBits(br, 4); - uint8_t v = kCodeLengthPrefixValue[ix]; - BrotliDropBits(br, kCodeLengthPrefixLength[ix]); - s->code_length_code_lengths[code_len_idx] = v; - BROTLI_LOG_ARRAY_INDEX(s->code_length_code_lengths, code_len_idx); - if (v != 0) { - space = space - (32U >> v); - ++num_codes; - ++s->code_length_histo[v]; - if (space - 1U >= 32U) { - /* space is 0 or wrapped around */ - break; - } - } - } - if (!(num_codes == 1 || space == 0)) { - return BROTLI_FAILURE(); + sizeof(s->code_length_code_lengths)); + s->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX; + goto Complex; + } + /* No break, transit to the next state. */ + + case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE: + /* Read symbols, codes & code lengths directly. */ + if (!BrotliSafeReadBits(br, 2, &s->symbol)) { /* num_symbols */ + s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->sub_loop_counter = 0; + /* No break, transit to the next state. */ + case BROTLI_STATE_HUFFMAN_SIMPLE_READ: { + BrotliResult result = ReadSimpleHuffmanSymbols(alphabet_size, s); + if (result != BROTLI_RESULT_SUCCESS) { + return result; + } + /* No break, transit to the next state. */ + } + case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: { + uint32_t table_size; + if (s->symbol == 3) { + uint32_t bits; + if (!BrotliSafeReadBits(br, 1, &bits)) { + s->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } + s->symbol += bits; + } + BROTLI_LOG_UINT(s->symbol); + table_size = BrotliBuildSimpleHuffmanTable( + table, HUFFMAN_TABLE_BITS, s->symbols_lists_array, s->symbol); + if (opt_table_size) { + *opt_table_size = table_size; + } + s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; + return BROTLI_RESULT_SUCCESS; + } + +Complex: /* Decode Huffman-coded code lengths. */ + case BROTLI_STATE_HUFFMAN_COMPLEX: { + uint32_t i; + BrotliResult result = ReadCodeLengthCodeLengths(s); + if (result != BROTLI_RESULT_SUCCESS) { + return result; } BrotliBuildCodeLengthsHuffmanTable(s->table, s->code_length_code_lengths, @@ -443,89 +741,25 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_size, s->space = 32768; s->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS; /* No break, transit to the next state. */ + } case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: { - uint32_t symbol = s->symbol; - uint32_t repeat = s->repeat; - uint32_t space = s->space; - uint8_t prev_code_len = s->prev_code_len; - uint8_t repeat_code_len = s->repeat_code_len; - uint16_t* symbol_lists = s->symbol_lists; - uint16_t* code_length_histo = s->code_length_histo; - int* next_symbol = s->next_symbol; - while (symbol < alphabet_size && space > 0) { - const HuffmanCode* p = s->table; - uint8_t code_len; - if (!BrotliCheckInputAmount(br, 8)) { - s->symbol = symbol; - s->repeat = repeat; - s->prev_code_len = prev_code_len; - s->repeat_code_len = repeat_code_len; - s->space = space; - return BROTLI_RESULT_NEEDS_MORE_INPUT; - } - p += BrotliGetBits(br, BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH); - BrotliDropBits(br, p->bits); /* Use 1..5 bits */ - code_len = (uint8_t)p->value; /* code_len == 0..17 */ - if (code_len < kCodeLengthRepeatCode) { - repeat = 0; - if (code_len != 0) { /* code_len == 1..15 */ - symbol_lists[next_symbol[code_len]] = (uint16_t)symbol; - next_symbol[code_len] = (int)symbol; - prev_code_len = code_len; - space -= 32768U >> code_len; - code_length_histo[code_len]++; - } - symbol++; - } else { /* code_len == 16..17, extra_bits == 2..3 */ - uint32_t repeat_delta = BrotliReadBits(br, code_len - 14U); - uint32_t old_repeat; - uint8_t new_len = 0; - if (code_len == kCodeLengthRepeatCode) { - new_len = prev_code_len; - } - if (repeat_code_len != new_len) { - repeat = 0; - repeat_code_len = new_len; - } - old_repeat = repeat; - if (repeat > 0) { - repeat -= 2; - repeat <<= code_len - 14; - } - repeat += repeat_delta + 3; - repeat_delta = repeat - old_repeat; /* repeat_delta >= 3 */ - /* So, for extra 2..3 bits we produce more than 2 symbols. - Consequently, at most 5 bits per symbol are used. */ - if (symbol + repeat_delta > alphabet_size) { - return BROTLI_FAILURE(); - } - if (repeat_code_len != 0) { - unsigned last = symbol + repeat_delta; - int next = next_symbol[repeat_code_len]; - do { - symbol_lists[next] = (uint16_t)symbol; - next = (int)symbol; - } while (++symbol != last); - next_symbol[repeat_code_len] = next; - space -= repeat_delta << (15 - repeat_code_len); - code_length_histo[repeat_code_len] = (uint16_t) - (code_length_histo[repeat_code_len] + repeat_delta); - } else { - symbol += repeat_delta; - } - } + uint32_t table_size; + BrotliResult result = ReadSymbolCodeLengths(alphabet_size, s); + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + result = SafeReadSymbolCodeLengths(alphabet_size, s); } - if (space != 0) { - BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", space)); + if (result != BROTLI_RESULT_SUCCESS) { + return result; + } + + if (s->space != 0) { + BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", s->space)); return BROTLI_FAILURE(); } - { - uint32_t table_size = BrotliBuildHuffmanTable( - table, HUFFMAN_TABLE_BITS, symbol_lists, - s->code_length_histo); - if (opt_table_size) { - *opt_table_size = table_size; - } + table_size = BrotliBuildHuffmanTable(table, HUFFMAN_TABLE_BITS, + s->symbol_lists, s->code_length_histo); + if (opt_table_size) { + *opt_table_size = table_size; } s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; return BROTLI_RESULT_SUCCESS; @@ -537,13 +771,41 @@ static BrotliResult ReadHuffmanCode(uint32_t alphabet_size, } /* Decodes a block length by reading 3..39 bits. */ -static BROTLI_INLINE int ReadBlockLength(const HuffmanCode* table, - BrotliBitReader* br) { +static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table, + BrotliBitReader* br) { uint32_t code; uint32_t nbits; code = ReadSymbol(table, br); nbits = kBlockLengthPrefixCode[code].nbits; /* nbits == 2..24 */ - return kBlockLengthPrefixCode[code].offset + (int)BrotliReadBits(br, nbits); + return kBlockLengthPrefixCode[code].offset + BrotliReadBits(br, nbits); +} + +/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then + reading can't be continued with ReadBlockLength. */ +static BROTLI_INLINE int SafeReadBlockLength(BrotliState* s, + uint32_t* result, + const HuffmanCode* table, + BrotliBitReader* br) { + uint32_t index; + if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) { + if (!SafeReadSymbol(table, br, &index)) { + return 0; + } + } else { + index = s->block_length_index; + } + { + uint32_t bits; + uint32_t nbits = kBlockLengthPrefixCode[index].nbits; /* nbits == 2..24 */ + if (!BrotliSafeReadBits(br, nbits, &bits)) { + s->block_length_index = index; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX; + return 0; + } + *result = kBlockLengthPrefixCode[index].offset + bits; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + return 1; + } } /* Transform: @@ -597,12 +859,6 @@ static BROTLI_NOINLINE void InverseMoveToFrontTransform(uint8_t* v, state->mtf_upper_bound = upper_bound; } -/* Expose function for testing. Will be removed by linker as unused. */ -void InverseMoveToFrontTransformForTesting( - uint8_t* v, uint32_t l, BrotliState* s) { - InverseMoveToFrontTransform(v, l, s); -} - /* Decodes a series of Huffman table using ReadHuffmanCode function. */ static BrotliResult HuffmanTreeGroupDecode(HuffmanTreeGroup* group, @@ -640,7 +896,6 @@ static BrotliResult DecodeContextMap(uint32_t context_map_size, BrotliState* s) { BrotliBitReader* br = &s->br; BrotliResult result = BROTLI_RESULT_SUCCESS; - int use_rle_for_zeros; switch((int)s->substate_context_map) { case BROTLI_STATE_CONTEXT_MAP_NONE: @@ -662,41 +917,65 @@ static BrotliResult DecodeContextMap(uint32_t context_map_size, } s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX; /* No break, continue to next state. */ - case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: - if (!BrotliWarmupBitReader(br) || !BrotliCheckInputAmount(br, 8)) { + case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: { + uint32_t bits; + /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe + to peek 4 bits ahead. */ + if (!BrotliSafeGetBits(br, 5, &bits)) { return BROTLI_RESULT_NEEDS_MORE_INPUT; } - use_rle_for_zeros = (int)BrotliReadBits(br, 1); - if (use_rle_for_zeros) { - s->max_run_length_prefix = BrotliReadBits(br, 4) + 1; + if ((bits & 1) != 0) { /* Use RLE for zeroes. */ + s->max_run_length_prefix = (bits >> 1) + 1; + BrotliDropBits(br, 5); } else { s->max_run_length_prefix = 0; + BrotliDropBits(br, 1); } BROTLI_LOG_UINT(s->max_run_length_prefix); s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN; /* No break, continue to next state. */ + } case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: result = ReadHuffmanCode(*num_htrees + s->max_run_length_prefix, s->context_map_table, NULL, s); if (result != BROTLI_RESULT_SUCCESS) return result; + s->code = 0xFFFF; s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE; /* No break, continue to next state. */ case BROTLI_STATE_CONTEXT_MAP_DECODE: { uint32_t context_index = s->context_index; uint32_t max_run_length_prefix = s->max_run_length_prefix; uint8_t* context_map = *context_map_arg; - uint32_t code; + uint32_t code = s->code; + if (code != 0xFFFF) { + goto rleCode; + } while (context_index < context_map_size) { - if (!BrotliCheckInputAmount(br, 32)) { + if (!SafeReadSymbol(s->context_map_table, br, &code)) { + s->code = 0xFFFF; s->context_index = context_index; return BROTLI_RESULT_NEEDS_MORE_INPUT; } - code = ReadSymbol(s->context_map_table, br); BROTLI_LOG_UINT(code); + if (code == 0) { context_map[context_index++] = 0; - } else if (code <= max_run_length_prefix) { - uint32_t reps = (1U << code) + BrotliReadBits(br, code); + continue; + } + if (code > max_run_length_prefix) { + context_map[context_index++] = + (uint8_t)(code - max_run_length_prefix); + continue; + } +rleCode: + { + uint32_t reps; + if (!BrotliSafeReadBits(br, code, &reps)) { + s->code = code; + s->context_index = context_index; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + reps += 1U << code; BROTLI_LOG_UINT(reps); if (context_index + reps > context_map_size) { return BROTLI_FAILURE(); @@ -704,13 +983,18 @@ static BrotliResult DecodeContextMap(uint32_t context_map_size, do { context_map[context_index++] = 0; } while (--reps); - } else { - context_map[context_index++] = - (uint8_t)(code - max_run_length_prefix); } } - if (BrotliReadBits(br, 1)) { - InverseMoveToFrontTransform(context_map, context_map_size, s); + /* No break, continue to next state. */ + } + case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: { + uint32_t bits; + if (!BrotliSafeReadBits(br, 1, &bits)) { + s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + if (bits != 0) { + InverseMoveToFrontTransform(*context_map_arg, context_map_size, s); } s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE; return BROTLI_RESULT_SUCCESS; @@ -721,15 +1005,32 @@ static BrotliResult DecodeContextMap(uint32_t context_map_size, } /* Decodes a command or literal and updates block type ringbuffer. - Reads 0..15 bits. */ -static void DecodeBlockType(const uint32_t max_block_type, - const HuffmanCode* trees, - int tree_type, - uint32_t* ringbuffers, - BrotliBitReader* br) { - uint32_t* ringbuffer = ringbuffers + tree_type * 2; - uint32_t block_type = ReadSymbol( - &trees[tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeBlockTypeAndLength(int safe, + BrotliState* s, int tree_type) { + uint32_t max_block_type = s->num_block_types[tree_type]; + int tree_offset = tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE; + const HuffmanCode* type_tree = &s->block_type_trees[tree_offset]; + const HuffmanCode* len_tree = &s->block_len_trees[tree_offset]; + BrotliBitReader* br = &s->br; + uint32_t* ringbuffer = &s->block_type_rb[tree_type * 2]; + uint32_t block_type; + + /* Read 0..15 + 3..39 bits */ + if (!safe) { + block_type = ReadSymbol(type_tree, br); + s->block_length[tree_type] = ReadBlockLength(len_tree, br); + } else { + BrotliBitReaderState memento; + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(type_tree, br, &block_type)) return 0; + if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) { + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + BrotliBitReaderRestoreState(br, &memento); + return 0; + } + } + if (block_type == 1) { block_type = ringbuffer[1] + 1; } else if (block_type == 0) { @@ -742,17 +1043,18 @@ static void DecodeBlockType(const uint32_t max_block_type, } ringbuffer[0] = ringbuffer[1]; ringbuffer[1] = block_type; + return 1; } /* Decodes the block type and updates the state for literal context. - Reads 18..54 bits. */ -static void DecodeBlockTypeWithContext(BrotliState* s, - BrotliBitReader* br) { + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeLiteralBlockSwitchInternal(int safe, + BrotliState* s) { uint8_t context_mode; uint32_t context_offset; - DecodeBlockType(s->num_block_types[0], s->block_type_trees, 0, - s->block_type_rb, br); /* Reads 0..15 bits. */ - s->block_length[0] = ReadBlockLength(s->block_len_trees, br); /* 3..39 bits */ + if (!DecodeBlockTypeAndLength(safe, s, 0)) { + return 0; + } context_offset = s->block_type_rb[1] << kLiteralContextBits; s->context_map_slice = s->context_map + context_offset; s->literal_htree_index = s->context_map_slice[0]; @@ -760,115 +1062,125 @@ static void DecodeBlockTypeWithContext(BrotliState* s, context_mode = s->context_modes[s->block_type_rb[1]]; s->context_lookup1 = &kContextLookup[kContextLookupOffsets[context_mode]]; s->context_lookup2 = &kContextLookup[kContextLookupOffsets[context_mode + 1]]; + return 1; +} + +static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliState* s) { + DecodeLiteralBlockSwitchInternal(0, s); +} + +static int BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(BrotliState* s) { + return DecodeLiteralBlockSwitchInternal(1, s); +} + +/* Block switch for insert/copy length. + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeCommandBlockSwitchInternal(int safe, + BrotliState* s) { + if (!DecodeBlockTypeAndLength(safe, s, 1)) { + return 0; + } + s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]]; + return 1; +} + +static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliState* s) { + DecodeCommandBlockSwitchInternal(0, s); +} +static int BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(BrotliState* s) { + return DecodeCommandBlockSwitchInternal(1, s); +} + +/* Block switch for distance codes. + Reads 3..54 bits. */ +static int BROTLI_INLINE DecodeDistanceBlockSwitchInternal(int safe, + BrotliState* s) { + if (!DecodeBlockTypeAndLength(safe, s, 2)) { + return 0; + } + s->dist_context_map_slice = + s->dist_context_map + (s->block_type_rb[5] << kDistanceContextBits); + s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; + return 1; } -BrotliResult WriteRingBuffer(BrotliOutput output, - BrotliState* s) { - int num_written; +static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliState* s) { + DecodeDistanceBlockSwitchInternal(0, s); +} + +static int BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(BrotliState* s) { + return DecodeDistanceBlockSwitchInternal(1, s); +} + +static BrotliResult WriteRingBuffer(size_t* available_out, uint8_t** next_out, + size_t* total_out, BrotliState* s) { + size_t pos = (s->pos > s->ringbuffer_size) ? + (size_t)s->ringbuffer_size : (size_t)(s->pos); + uint8_t* start = s->ringbuffer + + (s->partial_pos_out & (size_t)s->ringbuffer_mask); + size_t partial_pos_rb = + (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos; + size_t to_write = (partial_pos_rb - s->partial_pos_out); + size_t num_written = *available_out; + if (num_written > to_write) { + num_written = to_write; + } if (s->meta_block_remaining_len < 0) { return BROTLI_FAILURE(); } - num_written = BrotliWrite( - output, s->ringbuffer + s->partially_written, - (size_t)(s->to_write - s->partially_written)); - BROTLI_LOG_UINT(s->partially_written); - BROTLI_LOG_UINT(s->to_write); + memcpy(*next_out, start, num_written); + *next_out += num_written; + *available_out -= num_written; + BROTLI_LOG_UINT(to_write); BROTLI_LOG_UINT(num_written); - if (num_written < 0) { - return BROTLI_FAILURE(); - } - s->partially_written += num_written; - if (s->partially_written < s->to_write) { + s->partial_pos_out += (size_t)num_written; + *total_out = s->partial_pos_out; + if (num_written < to_write) { return BROTLI_RESULT_NEEDS_MORE_OUTPUT; } return BROTLI_RESULT_SUCCESS; } -BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput(BrotliOutput output, - int pos, - BrotliState* s) { - BrotliResult result; - int num_read; - int nbytes; +static BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput( + size_t* available_out, uint8_t** next_out, size_t* total_out, + BrotliState* s) { /* State machine */ for (;;) { - switch ((int)s->substate_uncompressed) { - case BROTLI_STATE_UNCOMPRESSED_NONE: - nbytes = (int)BrotliGetRemainingBytes(&s->br); - /* For short lengths copy byte-by-byte */ - if (s->meta_block_remaining_len < 8 || - s->meta_block_remaining_len < nbytes) { - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_SHORT; - break; + switch (s->substate_uncompressed) { + case BROTLI_STATE_UNCOMPRESSED_NONE: { + int nbytes = (int)BrotliGetRemainingBytes(&s->br); + if (nbytes > s->meta_block_remaining_len) { + nbytes = s->meta_block_remaining_len; + } + if (s->pos + nbytes > s->ringbuffer_size) { + nbytes = s->ringbuffer_size - s->pos; } /* Copy remaining bytes from s->br.buf_ to ringbuffer. */ - BrotliCopyBytes(&s->ringbuffer[pos], &s->br, (size_t)nbytes); - pos += nbytes; + BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes); + s->pos += nbytes; s->meta_block_remaining_len -= nbytes; - if (pos >= s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; - break; - } - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_COPY; - break; - case BROTLI_STATE_UNCOMPRESSED_SHORT: - if (!BrotliWarmupBitReader(&s->br)) { - return BROTLI_RESULT_NEEDS_MORE_INPUT; - } - while (s->meta_block_remaining_len > 0) { - if (!BrotliCheckInputAmount(&s->br, 8)) { - return BROTLI_RESULT_NEEDS_MORE_INPUT; + if (s->pos < s->ringbuffer_size) { + if (s->meta_block_remaining_len == 0) { + return BROTLI_RESULT_SUCCESS; } - s->ringbuffer[pos++] = (uint8_t)BrotliReadBits(&s->br, 8); - s->meta_block_remaining_len--; - } - if (pos >= s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; - } else { - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; - return BROTLI_RESULT_SUCCESS; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } - /* No break, if state is updated, continue to next state */ - case BROTLI_STATE_UNCOMPRESSED_WRITE: - result = WriteRingBuffer(output, s); + s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; + /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ + /* No break, continue to next state */ + } + case BROTLI_STATE_UNCOMPRESSED_WRITE: { + BrotliResult result = WriteRingBuffer( + available_out, next_out, total_out, s); if (result != BROTLI_RESULT_SUCCESS) { return result; } - pos &= s->ringbuffer_mask; + s->pos = 0; + s->rb_roundtrips++; s->max_distance = s->max_backward_distance; - /* If we wrote past the logical end of the ringbuffer, copy the tail - of the ringbuffer to its beginning and flush the ringbuffer to the - output. */ - memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)pos); - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_COPY; - /* No break, continue to next state */ - case BROTLI_STATE_UNCOMPRESSED_COPY: - /* Copy straight from the input onto the ringbuffer. The ringbuffer will - be flushed to the output at a later time. */ - nbytes = s->meta_block_remaining_len; - if (pos + nbytes > s->ringbuffer_size) { - nbytes = s->ringbuffer_size - pos; - } - num_read = BrotliRead(s->br.input_, &s->ringbuffer[pos], - (size_t)nbytes); - pos += num_read; - s->meta_block_remaining_len -= num_read; - if (num_read < nbytes) { - if (num_read < 0) return BROTLI_FAILURE(); - return BROTLI_RESULT_NEEDS_MORE_INPUT; - } - if (pos == s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE; - break; - } s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; - return BROTLI_RESULT_SUCCESS; + break; + } } } return BROTLI_FAILURE(); @@ -877,36 +1189,27 @@ BrotliResult BROTLI_NOINLINE CopyUncompressedBlockToOutput(BrotliOutput output, int BrotliDecompressedSize(size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size) { - BrotliMemInput memin; - BrotliInput in = BrotliInitMemInput(encoded_buffer, encoded_size, &memin); - BrotliBitReader br; BrotliState s; int next_block_header; - size_t offset; BrotliStateInit(&s); - BrotliInitBitReader(&br, in); - if (!BrotliReadInput(&br, 1) || !BrotliWarmupBitReader(&br)) { + s.br.next_in = encoded_buffer; + s.br.avail_in = encoded_size; + if (!BrotliWarmupBitReader(&s.br)) { return 0; } - DecodeWindowBits(&br); - if (DecodeMetaBlockLength(&s, &br) != BROTLI_RESULT_SUCCESS) { + DecodeWindowBits(&s.br); + if (DecodeMetaBlockLength(&s, &s.br) != BROTLI_RESULT_SUCCESS) { return 0; } *decoded_size = (size_t)s.meta_block_remaining_len; if (s.is_last_metablock) { return 1; } - if (!s.is_uncompressed || !BrotliJumpToByteBoundary(&br)) { + if (!s.is_uncompressed || !BrotliJumpToByteBoundary(&s.br)) { return 0; } - next_block_header = BrotliPeekByte(&br, (size_t)s.meta_block_remaining_len); - if (next_block_header != -1) { - return (next_block_header & 3) == 3; - } - /* Currently bit reader can't peek outside of its buffer... */ - offset = BROTLI_READ_SIZE - BrotliGetRemainingBytes(&br); - offset += (size_t)s.meta_block_remaining_len; - return (offset < encoded_size) && ((encoded_buffer[offset] & 3) == 3); + next_block_header = BrotliPeekByte(&s.br, (size_t)s.meta_block_remaining_len); + return (next_block_header != -1) && ((next_block_header & 3) == 3); } /* Allocates the smallest feasible ring buffer. @@ -918,9 +1221,12 @@ int BrotliDecompressedSize(size_t encoded_size, processed. When this method is called, metablock size and flags MUST be decoded. */ -int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s, +static int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s, BrotliBitReader* br) { - static const int kRingBufferWriteAheadSlack = BROTLI_READ_SIZE; + /* We need the slack region for the following reasons: + - doing up to two 16-byte copies for fast backward copying + - inserting transformed dictionary word (5 prefix + 24 base + 8 suffix) */ + static const int kRingBufferWriteAheadSlack = 42; int is_last = s->is_last_metablock; s->ringbuffer_size = 1 << s->window_bits; @@ -950,8 +1256,7 @@ int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s, s->ringbuffer_mask = s->ringbuffer_size - 1; s->ringbuffer = (uint8_t*)malloc((size_t)(s->ringbuffer_size + - kRingBufferWriteAheadSlack + - kBrotliMaxDictionaryWordLength)); + kRingBufferWriteAheadSlack + kBrotliMaxDictionaryWordLength)); if (s->ringbuffer == 0) { return 0; } @@ -966,17 +1271,527 @@ int BROTLI_NOINLINE BrotliAllocateRingBuffer(BrotliState* s, return 1; } +/* Reads 1..256 2-bit context modes. */ +static BrotliResult ReadContextModes(BrotliState* s) { + BrotliBitReader* br = &s->br; + int i = s->loop_counter; + + while (i < (int)s->num_block_types[0]) { + uint32_t bits; + if (!BrotliSafeReadBits(br, 2, &bits)) { + s->loop_counter = i; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + s->context_modes[i] = (uint8_t)(bits << 1); + BROTLI_LOG_ARRAY_INDEX(s->context_modes, i); + i++; + } + return BROTLI_RESULT_SUCCESS; +} + +static void BROTLI_INLINE TakeDistanceFromRingBuffer(BrotliState* s) { + if (s->distance_code == 0) { + --s->dist_rb_idx; + s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; + } else { + int distance_code = s->distance_code << 1; + /* kDistanceShortCodeIndexOffset has 2-bit values from LSB: */ + /* 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */ + const uint32_t kDistanceShortCodeIndexOffset = 0xaaafff1b; + /* kDistanceShortCodeValueOffset has 2-bit values from LSB: */ + /*-0, 0,-0, 0,-1, 1,-2, 2,-3, 3,-1, 1,-2, 2,-3, 3 */ + const uint32_t kDistanceShortCodeValueOffset = 0xfa5fa500; + int v = (s->dist_rb_idx + + (int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3; + s->distance_code = s->dist_rb[v]; + v = (int)(kDistanceShortCodeValueOffset >> distance_code) & 0x3; + if ((distance_code & 0x3) != 0) { + s->distance_code += v; + } else { + s->distance_code -= v; + if (s->distance_code <= 0) { + /* A huge distance will cause a BROTLI_FAILURE() soon. */ + /* This is a little faster than failing here. */ + s->distance_code = 0x0fffffff; + } + } + } +} + +static BROTLI_INLINE int SafeReadBits( + BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) { + if (n_bits != 0) { + return BrotliSafeReadBits(br, n_bits, val); + } else { + *val = 0; + return 1; + } +} + +/* Precondition: s->distance_code < 0 */ +static int BROTLI_INLINE ReadDistanceInternal(int safe, + BrotliState* s, BrotliBitReader* br) { + int distval; + BrotliBitReaderState memento; + HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index]; + if (!safe) { + s->distance_code = (int)ReadSymbol(distance_tree, br); + } else { + uint32_t code; + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(distance_tree, br, &code)) { + return 0; + } + s->distance_code = (int)code; + } + /* Convert the distance code to the actual distance by possibly */ + /* looking up past distances from the s->ringbuffer. */ + if ((s->distance_code & ~0xf) == 0) { + TakeDistanceFromRingBuffer(s); + --s->block_length[2]; + return 1; + } + distval = s->distance_code - (int)s->num_direct_distance_codes; + if (distval >= 0) { + uint32_t nbits; + int postfix; + int offset; + if (!safe && (s->distance_postfix_bits == 0)) { + nbits = ((uint32_t)distval >> 1) + 1; + offset = ((2 + (distval & 1)) << nbits) - 4; + s->distance_code = (int)s->num_direct_distance_codes + + offset + (int)BrotliReadBits(br, nbits); + } else { + /* This branch also works well when s->distance_postfix_bits == 0 */ + uint32_t bits; + postfix = distval & s->distance_postfix_mask; + distval >>= s->distance_postfix_bits; + nbits = ((uint32_t)distval >> 1) + 1; + if (safe) { + if (!SafeReadBits(br, nbits, &bits)) { + s->distance_code = -1; /* Restore precondition. */ + BrotliBitReaderRestoreState(br, &memento); + return 0; + } + } else { + bits = BrotliReadBits(br, nbits); + } + offset = ((2 + (distval & 1)) << nbits) - 4; + s->distance_code = (int)s->num_direct_distance_codes + + ((offset + (int)bits) << s->distance_postfix_bits) + postfix; + } + } + s->distance_code = s->distance_code - NUM_DISTANCE_SHORT_CODES + 1; + --s->block_length[2]; + return 1; +} + +static void BROTLI_INLINE ReadDistance(BrotliState* s, BrotliBitReader* br) { + ReadDistanceInternal(0, s, br); +} + +static int BROTLI_INLINE SafeReadDistance(BrotliState* s, BrotliBitReader* br) { + return ReadDistanceInternal(1, s, br); +} + +static int BROTLI_INLINE ReadCommandInternal(int safe, + BrotliState* s, BrotliBitReader* br, int* insert_length) { + uint32_t cmd_code; + uint32_t insert_len_extra = 0; + uint32_t copy_length; + CmdLutElement v; + BrotliBitReaderState memento; + if (!safe) { + cmd_code = ReadSymbol(s->htree_command, br); + } else { + BrotliBitReaderSaveState(br, &memento); + if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) { + return 0; + } + } + v = kCmdLut[cmd_code]; + s->distance_code = v.distance_code; + s->distance_context = v.context; + s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; + *insert_length = v.insert_len_offset; + if (!safe) { + if (PREDICT_FALSE(v.insert_len_extra_bits != 0)) { + insert_len_extra = BrotliReadBits(br, v.insert_len_extra_bits); + } + copy_length = BrotliReadBits(br, v.copy_len_extra_bits); + } else { + if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) || + !SafeReadBits(br, v.copy_len_extra_bits, ©_length)) { + BrotliBitReaderRestoreState(br, &memento); + return 0; + } + } + s->copy_length = (int)copy_length + v.copy_len_offset; + --s->block_length[1]; + *insert_length += (int)insert_len_extra; + return 1; +} + +static void BROTLI_INLINE ReadCommand(BrotliState* s, BrotliBitReader* br, + int* insert_length) { + ReadCommandInternal(0, s, br, insert_length); +} + +static int BROTLI_INLINE SafeReadCommand(BrotliState* s, BrotliBitReader* br, + int* insert_length) { + return ReadCommandInternal(1, s, br, insert_length); +} + +static BROTLI_INLINE int WarmupBitReader(int safe, BrotliBitReader* const br) { + if (safe) { + return 1; + } + return BrotliWarmupBitReader(br); +} + +static BROTLI_INLINE int CheckInputAmount(int safe, + BrotliBitReader* const br, size_t num) { + if (safe) { + return 1; + } + return BrotliCheckInputAmount(br, num); +} + +#define BROTLI_SAFE(METHOD) { \ + if (safe) { \ + if (! Safe ## METHOD ) { \ + result = BROTLI_RESULT_NEEDS_MORE_INPUT; \ + goto saveStateAndReturn; \ + } \ + } else { \ + METHOD ; \ + } \ +} + +static BROTLI_INLINE BrotliResult ProcessCommandsInternal(int safe, + BrotliState* s) { + int pos = s->pos; + int i = s->loop_counter; + BrotliResult result = BROTLI_RESULT_SUCCESS; + BrotliBitReader* br = &s->br; + + if (!CheckInputAmount(safe, br, 28) || !WarmupBitReader(safe, br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + + /* Jump into state machine. */ + if (s->state == BROTLI_STATE_COMMAND_BEGIN) { + goto CommandBegin; + } else if (s->state == BROTLI_STATE_COMMAND_INNER) { + goto CommandInner; + } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) { + goto CommandPostDecodeLiterals; + } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) { + goto CommandPostWrapCopy; + } else { + return BROTLI_FAILURE(); + } + +CommandBegin: + if (safe) { + s->state = BROTLI_STATE_COMMAND_BEGIN; + } + if (!CheckInputAmount(safe, br, 28)) { /* 156 bits + 7 bytes */ + s->state = BROTLI_STATE_COMMAND_BEGIN; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (PREDICT_FALSE(s->block_length[1] == 0)) { + BROTLI_SAFE(DecodeCommandBlockSwitch(s)); + goto CommandBegin; + } + /* Read the insert/copy length in the command */ + BROTLI_SAFE(ReadCommand(s, br, &i)); + BROTLI_LOG_UINT(i); + BROTLI_LOG_UINT(s->copy_length); + BROTLI_LOG_UINT(s->distance_code); + if (i == 0) { + goto CommandPostDecodeLiterals; + } + s->meta_block_remaining_len -= i; + +CommandInner: + if (safe) { + s->state = BROTLI_STATE_COMMAND_INNER; + } + /* Read the literals in the command */ + if (s->trivial_literal_context) { + uint32_t bits; + uint32_t value; + PreloadSymbol(safe, s->literal_htree, br, &bits, &value); + do { + if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */ + s->state = BROTLI_STATE_COMMAND_INNER; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (PREDICT_FALSE(s->block_length[0] == 0)) { + BROTLI_SAFE(DecodeLiteralBlockSwitch(s)); + PreloadSymbol(safe, s->literal_htree, br, &bits, &value); + } + if (!safe) { + s->ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol( + s->literal_htree, br, &bits, &value); + } else { + uint32_t literal; + if (!SafeReadSymbol(s->literal_htree, br, &literal)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + s->ringbuffer[pos] = (uint8_t)literal; + } + --s->block_length[0]; + BROTLI_LOG_UINT(s->literal_htree_index); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos); + ++pos; + if (PREDICT_FALSE(pos == s->ringbuffer_size)) { + s->state = BROTLI_STATE_COMMAND_INNER_WRITE; + --i; + goto saveStateAndReturn; + } + } while (--i != 0); + } else { + uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; + uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; + do { + const HuffmanCode* hc; + uint8_t context; + if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */ + s->state = BROTLI_STATE_COMMAND_INNER; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + if (PREDICT_FALSE(s->block_length[0] == 0)) { + BROTLI_SAFE(DecodeLiteralBlockSwitch(s)); + } + context = s->context_lookup1[p1] | s->context_lookup2[p2]; + BROTLI_LOG_UINT(context); + hc = s->literal_hgroup.htrees[s->context_map_slice[context]]; + p2 = p1; + if (!safe) { + p1 = (uint8_t)ReadSymbol(hc, br); + } else { + uint32_t literal; + if (!SafeReadSymbol(hc, br, &literal)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + goto saveStateAndReturn; + } + p1 = (uint8_t)literal; + } + s->ringbuffer[pos] = p1; + --s->block_length[0]; + BROTLI_LOG_UINT(s->context_map_slice[context]); + BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); + ++pos; + if (PREDICT_FALSE(pos == s->ringbuffer_size)) { + s->state = BROTLI_STATE_COMMAND_INNER_WRITE; + --i; + goto saveStateAndReturn; + } + } while (--i != 0); + } + if (s->meta_block_remaining_len <= 0) { + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } + +CommandPostDecodeLiterals: + if (safe) { + s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS; + } + if (s->distance_code >= 0) { + --s->dist_rb_idx; + s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; + goto postReadDistance; /* We already have the implicit distance */ + } + /* Read distance code in the command, unless it was implicitly zero. */ + if (PREDICT_FALSE(s->block_length[2] == 0)) { + BROTLI_SAFE(DecodeDistanceBlockSwitch(s)); + } + BROTLI_SAFE(ReadDistance(s, br)); +postReadDistance: + BROTLI_LOG_UINT(s->distance_code); + if (s->max_distance != s->max_backward_distance) { + if (pos < s->max_backward_distance_minus_custom_dict_size) { + s->max_distance = pos + s->custom_dict_size; + } else { + s->max_distance = s->max_backward_distance; + } + } + i = s->copy_length; + /* Apply copy of LZ77 back-reference, or static dictionary reference if + the distance is larger than the max LZ77 distance */ + if (s->distance_code > s->max_distance) { + if (i >= kBrotliMinDictionaryWordLength && + i <= kBrotliMaxDictionaryWordLength) { + int offset = kBrotliDictionaryOffsetsByLength[i]; + int word_id = s->distance_code - s->max_distance - 1; + uint32_t shift = kBrotliDictionarySizeBitsByLength[i]; + int mask = (int)BitMask(shift); + int word_idx = word_id & mask; + int transform_idx = word_id >> shift; + offset += word_idx * i; + if (transform_idx < kNumTransforms) { + const uint8_t* word = &kBrotliDictionary[offset]; + int len = i; + if (transform_idx == 0) { + memcpy(&s->ringbuffer[pos], word, (size_t)len); + } else { + len = TransformDictionaryWord( + &s->ringbuffer[pos], word, len, transform_idx); + } + pos += len; + s->meta_block_remaining_len -= len; + if (pos >= s->ringbuffer_size) { + /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ + s->state = BROTLI_STATE_COMMAND_POST_WRITE_1; + goto saveStateAndReturn; + } + } else { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", + pos, s->distance_code, i, + s->meta_block_remaining_len)); + return BROTLI_FAILURE(); + } + } else { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", pos, s->distance_code, i, + s->meta_block_remaining_len)); + return BROTLI_FAILURE(); + } + } else { + const uint8_t *ringbuffer_end_minus_copy_length = + s->ringbuffer_end - i; + uint8_t* copy_src = &s->ringbuffer[ + (pos - s->distance_code) & s->ringbuffer_mask]; + uint8_t* copy_dst = &s->ringbuffer[pos]; + /* update the recent distances cache */ + s->dist_rb[s->dist_rb_idx & 3] = s->distance_code; + ++s->dist_rb_idx; + s->meta_block_remaining_len -= i; + if (PREDICT_FALSE(s->meta_block_remaining_len < 0)) { + BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " + "len: %d bytes left: %d\n", pos, s->distance_code, i, + s->meta_block_remaining_len)); + return BROTLI_FAILURE(); + } + /* There is 128+ bytes of slack in the ringbuffer allocation. + Also, we have 16 short codes, that make these 16 bytes irrelevant + in the ringbuffer. Let's copy over them as a first guess. + */ + memmove16(copy_dst, copy_src); + /* Now check if the copy extends over the ringbuffer end, + or if the copy overlaps with itself, if yes, do wrap-copy. */ + if (copy_src < copy_dst) { + if (copy_dst >= ringbuffer_end_minus_copy_length) { + goto CommandPostWrapCopy; + } + if (copy_src + i > copy_dst) { + goto postSelfintersecting; + } + } else { + if (copy_src >= ringbuffer_end_minus_copy_length) { + goto CommandPostWrapCopy; + } + if (copy_dst + i > copy_src) { + goto postSelfintersecting; + } + } + pos += i; + if (i > 16) { + if (i > 32) { + memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16)); + } else { + /* This branch covers about 45% cases. + Fixed size short copy allows more compiler optimizations. */ + memmove16(copy_dst + 16, copy_src + 16); + } + } + } + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } +postSelfintersecting: + while (--i >= 0) { + s->ringbuffer[pos] = + s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; + ++pos; + } + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } + +CommandPostWrapCopy: + s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; + while (--i >= 0) { + s->ringbuffer[pos] = + s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; + ++pos; + if (pos == s->ringbuffer_size) { + /*s->partial_pos_rb += (size_t)s->ringbuffer_size;*/ + s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; + goto saveStateAndReturn; + } + } + if (s->meta_block_remaining_len <= 0) { + /* Next metablock, if any */ + s->state = BROTLI_STATE_METABLOCK_DONE; + goto saveStateAndReturn; + } else { + goto CommandBegin; + } + +saveStateAndReturn: + s->pos = pos; + s->loop_counter = i; + return result; +} + +#undef BROTLI_SAFE + +static BROTLI_NOINLINE BrotliResult ProcessCommands(BrotliState* s) { + return ProcessCommandsInternal(0, s); +} + +static BROTLI_NOINLINE BrotliResult SafeProcessCommands(BrotliState* s) { + return ProcessCommandsInternal(1, s); +} + BrotliResult BrotliDecompressBuffer(size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size, uint8_t* decoded_buffer) { - BrotliMemInput memin; - BrotliInput in = BrotliInitMemInput(encoded_buffer, encoded_size, &memin); - BrotliMemOutput mout; - BrotliOutput out = BrotliInitMemOutput(decoded_buffer, *decoded_size, &mout); - BrotliResult success = BrotliDecompress(in, out); - *decoded_size = mout.pos; - return success; + BrotliState s; + BrotliResult result; + size_t total_out = 0; + size_t available_in = encoded_size; + const uint8_t* next_in = encoded_buffer; + size_t available_out = *decoded_size; + uint8_t* next_out = decoded_buffer; + BrotliStateInit(&s); + result = BrotliDecompressStream(&available_in, &next_in, &available_out, + &next_out, &total_out, &s); + *decoded_size = total_out; + BrotliStateCleanup(&s); + if (result != BROTLI_RESULT_SUCCESS) { + result = BROTLI_RESULT_ERROR; + } + return result; } BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output) { @@ -999,61 +1814,184 @@ BrotliResult BrotliDecompressBufferStreaming(size_t* available_in, uint8_t** next_out, size_t* total_out, BrotliState* s) { - BrotliMemInput memin; - BrotliInput in = BrotliInitMemInput(*next_in, *available_in, &memin); - BrotliMemOutput memout; - BrotliOutput out = BrotliInitMemOutput(*next_out, *available_out, &memout); - BrotliResult result = BrotliDecompressStreaming(in, out, finish, s); - /* The current implementation reads everything, so 0 bytes are available. */ - *next_in += memin.pos; - *available_in -= memin.pos; - /* Update the output position to where we write next. */ - *next_out += memout.pos; - *available_out -= memout.pos; - *total_out += memout.pos; + BrotliResult result = BrotliDecompressStream(available_in, next_in, + available_out, next_out, total_out, s); + if (finish && result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + result = BROTLI_FAILURE(); + } return result; } BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, int finish, BrotliState* s) { - uint8_t context; - int pos = s->pos; - int i = s->loop_counter; - uint32_t j; + const size_t kBufferSize = 65536; + BrotliResult result; + uint8_t* input_buffer; + uint8_t* output_buffer; + size_t avail_in; + const uint8_t* next_in; + size_t total_out; + + if (s->legacy_input_buffer == 0) { + s->legacy_input_buffer = (uint8_t*)malloc(kBufferSize); + } + if (s->legacy_output_buffer == 0) { + s->legacy_output_buffer = (uint8_t*)malloc(kBufferSize); + } + if (s->legacy_input_buffer == 0 || s->legacy_output_buffer == 0) { + return BROTLI_FAILURE(); + } + input_buffer = s->legacy_input_buffer; + output_buffer = s->legacy_output_buffer; + + /* Push remaining output. */ + if (s->legacy_output_len > s->legacy_output_pos) { + size_t to_write = s->legacy_output_len - s->legacy_output_pos; + int num_written = BrotliWrite( + output, output_buffer + s->legacy_output_pos, to_write); + if (num_written < 0) { + return BROTLI_FAILURE(); + } + s->legacy_output_pos += (size_t)num_written; + if ((size_t)num_written < to_write) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + } + s->legacy_output_pos = 0; + + avail_in = s->legacy_input_len - s->legacy_input_pos; + next_in = input_buffer + s->legacy_input_pos; + + while (1) { + size_t to_write; + int num_written; + size_t avail_out = kBufferSize; + uint8_t* next_out = output_buffer; + result = BrotliDecompressStream(&avail_in, &next_in, + &avail_out, &next_out, &total_out, s); + s->legacy_input_pos = (size_t)(next_out - input_buffer); + to_write = (size_t)(next_out - output_buffer); + num_written = BrotliWrite(output, output_buffer, to_write); + if (num_written < 0) { + return BROTLI_FAILURE(); + } + if ((size_t)num_written < to_write) { + s->legacy_output_len = to_write; + s->legacy_output_pos = (size_t)num_written; + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + int num_read = BrotliRead(input, input_buffer, kBufferSize); + if (num_read < 0 || (num_read == 0 && finish)) { + return BROTLI_FAILURE(); + } + if (num_read == 0) { + s->legacy_input_len = 0; + s->legacy_input_pos = 0; + return BROTLI_RESULT_NEEDS_MORE_INPUT; + } + avail_in = (size_t)num_read; + next_in = input_buffer; + s->legacy_input_len = avail_in; + s->legacy_input_pos = 0; + } else if (result != BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + /* Success or failure. */ + return result; + } + } +} + +/* Invariant: input stream is never overconsumed: + * invalid input implies that the whole stream is invalid -> any amount of + input could be read and discarded + * when result is "needs more input", then at leat one more byte is REQUIRED + to complete decoding; all input data MUST be consumed by decoder, so + client could swap the input buffer + * when result is "needs more output" decoder MUST ensure that it doesn't + hold more than 7 bits in bit reader; this saves client from swapping input + buffer ahead of time + * when result is "success" decoder MUST return all unused data back to input + buffer; this is possible because the invariant is hold on enter +*/ +BrotliResult BrotliDecompressStream(size_t* available_in, + const uint8_t** next_in, size_t* available_out, uint8_t** next_out, + size_t* total_out, BrotliState* s) { BrotliResult result = BROTLI_RESULT_SUCCESS; BrotliBitReader* br = &s->br; - int initial_remaining_len; - int bytes_copied; - uint8_t *copy_src; - uint8_t *copy_dst; - /* We need the slack region for the following reasons: - - doing up to two 16-byte copies for fast backward copying - - transforms - - flushing the input s->ringbuffer when decoding uncompressed blocks */ - s->br.input_ = input; + if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */ + br->avail_in = *available_in; + br->next_in = *next_in; + } else { + /* At least one byte of input is required. More than one byte of input may + be required to complete the transaction -> reading more data must be + done in a loop -> do it in a main loop. */ + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + br->next_in = &s->buffer.u8[0]; + } /* State machine */ for (;;) { - if (result != BROTLI_RESULT_SUCCESS) { + if (result != BROTLI_RESULT_SUCCESS) { /* Error | needs more input/output */ if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { - if (BrotliReadInput(br, finish)) { - result = BROTLI_RESULT_SUCCESS; - continue; - } - if (finish) { - BROTLI_LOG(("Unexpected end of input. State: %d\n", s->state)); - result = BROTLI_FAILURE(); + if (s->ringbuffer != 0) { /* Proactively push output. */ + WriteRingBuffer(available_out, next_out, total_out, s); + } + if (s->buffer_length != 0) { /* Used with internal buffer. */ + if (br->avail_in == 0) { /* Successfully finished read transaction. */ + /* Accamulator contains less than 8 bits, because internal buffer + is expanded byte-by-byte until it is enough to complete read. */ + s->buffer_length = 0; + /* Switch to input stream and restart. */ + result = BROTLI_RESULT_SUCCESS; + br->avail_in = *available_in; + br->next_in = *next_in; + continue; + } else if (*available_in != 0) { + /* Not enough data in buffer, but can take one more byte from + input stream. */ + result = BROTLI_RESULT_SUCCESS; + s->buffer.u8[s->buffer_length] = **next_in; + s->buffer_length++; + br->avail_in = s->buffer_length; + (*next_in)++; + (*available_in)--; + /* Retry with more data in buffer. */ + continue; + } + /* Can't finish reading and no more input.*/ + break; + } else { /* Input stream doesn't contain enough input. */ + /* Copy tail to internal buffer and return. */ + *next_in = br->next_in; + *available_in = br->avail_in; + while (*available_in) { + s->buffer.u8[s->buffer_length] = **next_in; + s->buffer_length++; + (*next_in)++; + (*available_in)--; + } + break; } + /* Unreachable. */ + } + + /* Fail or needs more output. */ + + if (s->buffer_length != 0) { + /* Just consumed the buffered input and produced some output. Otherwise + it would result in "needs more input". Reset internal buffer.*/ + s->buffer_length = 0; + } else { + /* Using input stream in last iteration. When decoder switches to input + stream it has less than 8 bits in accamulator, so it is safe to + return unused accamulator bits there. */ + BrotliBitReaderUnload(br); + *available_in = br->avail_in; + *next_in = br->next_in; } - break; /* Fail, or partial data. */ + break; } switch (s->state) { case BROTLI_STATE_UNINITED: - pos = 0; - BrotliInitBitReader(br, input); - - s->state = BROTLI_STATE_BITREADER_WARMUP; - /* No break, continue to next state */ - case BROTLI_STATE_BITREADER_WARMUP: /* Prepare to the first read. */ if (!BrotliWarmupBitReader(br)) { result = BROTLI_RESULT_NEEDS_MORE_INPUT; @@ -1085,13 +2023,12 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_BEGIN: BrotliStateMetablockBegin(s); - BROTLI_LOG_UINT(pos); + BROTLI_LOG_UINT(s->pos); s->state = BROTLI_STATE_METABLOCK_HEADER; /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_HEADER: result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */ if (result != BROTLI_RESULT_SUCCESS) { - i = s->loop_counter; /* Has been updated in DecodeMetaBlockLength. */ break; } BROTLI_LOG_UINT(s->is_last_metablock); @@ -1122,20 +2059,20 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, s->state = BROTLI_STATE_UNCOMPRESSED; break; } - i = 0; + s->loop_counter = 0; s->state = BROTLI_STATE_HUFFMAN_CODE_0; break; - case BROTLI_STATE_UNCOMPRESSED: - initial_remaining_len = s->meta_block_remaining_len; - /* pos is given as argument since s->pos is only updated at the end. */ - result = CopyUncompressedBlockToOutput(output, pos, s); - bytes_copied = initial_remaining_len - s->meta_block_remaining_len; - pos = (pos + bytes_copied) & s->ringbuffer_mask; + case BROTLI_STATE_UNCOMPRESSED: { + int bytes_copied = s->meta_block_remaining_len; + result = CopyUncompressedBlockToOutput( + available_out, next_out, total_out, s); + bytes_copied -= s->meta_block_remaining_len; if (result != BROTLI_RESULT_SUCCESS) { break; } s->state = BROTLI_STATE_METABLOCK_DONE; break; + } case BROTLI_STATE_METADATA: for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) { uint32_t bits; @@ -1150,63 +2087,61 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, } break; case BROTLI_STATE_HUFFMAN_CODE_0: - if (i >= 3) { - s->state = BROTLI_STATE_CONTEXT_MODES; + if (s->loop_counter >= 3) { + s->state = BROTLI_STATE_METABLOCK_HEADER_2; break; } /* Reads 1..11 bits. */ - result = DecodeVarLenUint8(s, br, &s->num_block_types[i]); + result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]); if (result != BROTLI_RESULT_SUCCESS) { break; } - s->num_block_types[i]++; - BROTLI_LOG_UINT(s->num_block_types[i]); - s->state = BROTLI_STATE_HUFFMAN_CODE_1; - /* No break, continue to next state */ - case BROTLI_STATE_HUFFMAN_CODE_1: - if (!BrotliWarmupBitReader(br)) { - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - if (s->num_block_types[i] >= 2) { - result = ReadHuffmanCode(s->num_block_types[i] + 2, - &s->block_type_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], - NULL, s); - if (result != BROTLI_RESULT_SUCCESS) break; - s->state = BROTLI_STATE_HUFFMAN_CODE_2; - } else { - i++; - s->state = BROTLI_STATE_HUFFMAN_CODE_0; + s->num_block_types[s->loop_counter]++; + BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]); + if (s->num_block_types[s->loop_counter] < 2) { + s->loop_counter++; break; } + s->state = BROTLI_STATE_HUFFMAN_CODE_1; + /* No break, continue to next state */ + case BROTLI_STATE_HUFFMAN_CODE_1: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_TABLE_SIZE; + result = ReadHuffmanCode(s->num_block_types[s->loop_counter] + 2, + &s->block_type_trees[tree_offset], NULL, s); + if (result != BROTLI_RESULT_SUCCESS) break; + s->state = BROTLI_STATE_HUFFMAN_CODE_2; /* No break, continue to next state */ - case BROTLI_STATE_HUFFMAN_CODE_2: + } + case BROTLI_STATE_HUFFMAN_CODE_2: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_TABLE_SIZE; result = ReadHuffmanCode(kNumBlockLengthCodes, - &s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], - NULL, s); + &s->block_len_trees[tree_offset], NULL, s); if (result != BROTLI_RESULT_SUCCESS) break; s->state = BROTLI_STATE_HUFFMAN_CODE_3; /* No break, continue to next state */ - case BROTLI_STATE_HUFFMAN_CODE_3: - if (!BrotliCheckInputAmount(br, 8)) { + } + case BROTLI_STATE_HUFFMAN_CODE_3: { + int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_TABLE_SIZE; + if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter], + &s->block_len_trees[tree_offset], br)) { result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } - s->block_length[i] = ReadBlockLength( /* Reads 3..39 bits. */ - &s->block_len_trees[i * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); - BROTLI_LOG_UINT(s->block_length[i]); - i++; + BROTLI_LOG_UINT(s->block_length[s->loop_counter]); + s->loop_counter++; s->state = BROTLI_STATE_HUFFMAN_CODE_0; break; - case BROTLI_STATE_CONTEXT_MODES: - /* We need up to 256 * 2 + 6 bits, this fits in 128 bytes. */ - if (!BrotliCheckInputAmount(br, 128)) { + } + case BROTLI_STATE_METABLOCK_HEADER_2: { + uint32_t bits; + if (!BrotliSafeReadBits(br, 6, &bits)) { result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } - s->distance_postfix_bits = BrotliReadBits(br, 2); + s->distance_postfix_bits = bits & BitMask(2); + bits >>= 2; s->num_direct_distance_codes = NUM_DISTANCE_SHORT_CODES + - (BrotliReadBits(br, 4) << s->distance_postfix_bits); + (bits << s->distance_postfix_bits); BROTLI_LOG_UINT(s->num_direct_distance_codes); BROTLI_LOG_UINT(s->distance_postfix_bits); s->distance_postfix_mask = (int)BitMask(s->distance_postfix_bits); @@ -1215,13 +2150,19 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, result = BROTLI_FAILURE(); break; } - for (j = 0; j < s->num_block_types[0]; ++j) { - s->context_modes[j] = (uint8_t)(BrotliReadBits(br, 2) << 1); - BROTLI_LOG_ARRAY_INDEX(s->context_modes, j); + s->loop_counter = 0; + s->state = BROTLI_STATE_CONTEXT_MODES; + /* No break, continue to next state */ + } + case BROTLI_STATE_CONTEXT_MODES: + result = ReadContextModes(s); + if (result != BROTLI_RESULT_SUCCESS) { + break; } s->state = BROTLI_STATE_CONTEXT_MAP_1; /* No break, continue to next state */ - case BROTLI_STATE_CONTEXT_MAP_1: + case BROTLI_STATE_CONTEXT_MAP_1: { + uint32_t j; result = DecodeContextMap(s->num_block_types[0] << kLiteralContextBits, &s->num_literal_htrees, &s->context_map, s); if (result != BROTLI_RESULT_SUCCESS) { @@ -1236,6 +2177,7 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, } s->state = BROTLI_STATE_CONTEXT_MAP_2; /* No break, continue to next state */ + } case BROTLI_STATE_CONTEXT_MAP_2: { uint32_t num_distance_codes = @@ -1259,13 +2201,13 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, return BROTLI_FAILURE(); } } - i = 0; + s->loop_counter = 0; s->state = BROTLI_STATE_TREE_GROUP; /* No break, continue to next state */ case BROTLI_STATE_TREE_GROUP: { HuffmanTreeGroup* hgroup = NULL; - switch (i) { + switch (s->loop_counter) { case 0: hgroup = &s->literal_hgroup; break; @@ -1279,8 +2221,8 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, result = HuffmanTreeGroupDecode(hgroup, s); } if (result != BROTLI_RESULT_SUCCESS) break; - i++; - if (i >= 3) { + s->loop_counter++; + if (s->loop_counter >= 3) { uint8_t context_mode = s->context_modes[s->block_type_rb[1]]; s->context_map_slice = s->context_map; s->dist_context_map_slice = s->dist_context_map; @@ -1294,377 +2236,43 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, } break; case BROTLI_STATE_COMMAND_BEGIN: - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } - /* Decoding of Brotli commands is the inner loop, jumping with goto makes it - 3% faster */ - CommandBegin: - if (!BrotliCheckInputAmount(br, 32)) { - s->state = BROTLI_STATE_COMMAND_BEGIN; - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - /* Read the insert/copy length in the command */ - if (s->block_length[1] == 0) { - /* Block switch for insert/copy length. Reads 0..15 bits. */ - DecodeBlockType(s->num_block_types[1], - s->block_type_trees, 1, - s->block_type_rb, br); - s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]]; - s->block_length[1] = ReadBlockLength( /* Reads 3..39 bits. */ - &s->block_len_trees[BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); - } - { - uint32_t cmd_code = ReadSymbol(s->htree_command, br); - int insert_len_extra = 0; - CmdLutElement v; - --s->block_length[1]; - v = kCmdLut[cmd_code]; - s->distance_code = v.distance_code; - s->distance_context = v.context; - s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; - i = v.insert_len_offset; - if (PREDICT_FALSE(v.insert_len_extra_bits != 0)) { - insert_len_extra = (int)BrotliReadBits(br, v.insert_len_extra_bits); - } - s->copy_length = (int)BrotliReadBits(br, v.copy_len_extra_bits) + - v.copy_len_offset; - i += insert_len_extra; - } - BROTLI_LOG_UINT(i); - BROTLI_LOG_UINT(s->copy_length); - BROTLI_LOG_UINT(s->distance_code); - if (i == 0) { - goto postDecodeLiterals; - } - s->meta_block_remaining_len -= i; - /* No break, go to next state */ case BROTLI_STATE_COMMAND_INNER: - /* Read the literals in the command */ - if (s->trivial_literal_context) { - uint32_t bits; - uint32_t value; - PreloadSymbol(s->literal_htree, br, &bits, &value); - do { - if (!BrotliCheckInputAmount(br, 64)) { - s->state = BROTLI_STATE_COMMAND_INNER; - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - if (PREDICT_FALSE(s->block_length[0] == 0)) { - /* Block switch for literals */ - DecodeBlockTypeWithContext(s, br); - PreloadSymbol(s->literal_htree, br, &bits, &value); - } - s->ringbuffer[pos] = - (uint8_t)ReadPreloadedSymbol(s->literal_htree, - br, &bits, &value); - --s->block_length[0]; - BROTLI_LOG_UINT(s->literal_htree_index); - BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos); - ++pos; - if (PREDICT_FALSE(pos == s->ringbuffer_size)) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_INNER_WRITE; - --i; - goto innerWrite; - } - } while (--i != 0); - } else { - uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask]; - uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; - do { - const HuffmanCode* hc; - if (!BrotliCheckInputAmount(br, 64)) { - s->state = BROTLI_STATE_COMMAND_INNER; - result = BROTLI_RESULT_NEEDS_MORE_INPUT; - break; - } - if (PREDICT_FALSE(s->block_length[0] == 0)) { - /* Block switch for literals */ - DecodeBlockTypeWithContext(s, br); - } - context = s->context_lookup1[p1] | s->context_lookup2[p2]; - BROTLI_LOG_UINT(context); - hc = s->literal_hgroup.htrees[s->context_map_slice[context]]; - --s->block_length[0]; - p2 = p1; - p1 = (uint8_t)ReadSymbol(hc, br); - s->ringbuffer[pos] = p1; - BROTLI_LOG_UINT(s->context_map_slice[context]); - BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); - ++pos; - if (PREDICT_FALSE(pos == s->ringbuffer_size)) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_INNER_WRITE; - --i; - goto innerWrite; - } - } while (--i != 0); - } - if (result != BROTLI_RESULT_SUCCESS) break; - if (s->meta_block_remaining_len <= 0) { - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } -postDecodeLiterals: - if (s->distance_code >= 0) { - --s->dist_rb_idx; - s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; - goto postReadDistance; /* We already have the implicit distance */ - } - /* Read distance code in the command, unless it was implicitly zero. */ - BROTLI_DCHECK(s->distance_code < 0); - if (s->block_length[2] == 0) { - /* Block switch for distance codes */ - uint32_t dist_context_offset; - DecodeBlockType(s->num_block_types[2], - s->block_type_trees, 2, - s->block_type_rb, br); /* Reads 0..15 bits. */ - s->block_length[2] = ReadBlockLength( /* Reads 3..39 bits. */ - &s->block_len_trees[2 * BROTLI_HUFFMAN_MAX_TABLE_SIZE], br); - dist_context_offset = s->block_type_rb[5] << kDistanceContextBits; - s->dist_context_map_slice = - s->dist_context_map + dist_context_offset; - s->dist_htree_index = s->dist_context_map_slice[s->distance_context]; - } - --s->block_length[2]; - s->distance_code = (int)ReadSymbol( - s->distance_hgroup.htrees[s->dist_htree_index], br); - /* Convert the distance code to the actual distance by possibly */ - /* looking up past distances from the s->ringbuffer. */ - if ((s->distance_code & ~0xf) == 0) { - if (s->distance_code == 0) { - --s->dist_rb_idx; - s->distance_code = s->dist_rb[s->dist_rb_idx & 3]; - } else { - int distance_code = s->distance_code << 1; - /* kDistanceShortCodeIndexOffset has 2-bit values from LSB: */ - /* 3, 2, 1, 0, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 */ - const uint32_t kDistanceShortCodeIndexOffset = 0xaaafff1b; - /* kDistanceShortCodeValueOffset has 2-bit values from LSB: */ - /* 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3 */ - const uint32_t kDistanceShortCodeValueOffset = 0xfa5fa500; - int v = (s->dist_rb_idx + - (int)(kDistanceShortCodeIndexOffset >> distance_code)) & 0x3; - s->distance_code = s->dist_rb[v]; - v = (int)(kDistanceShortCodeValueOffset >> distance_code) & 0x3; - if ((distance_code & 0x3) != 0) { - s->distance_code += v; - } else { - s->distance_code -= v; - if (s->distance_code <= 0) { - /* A huge distance will cause a BROTLI_FAILURE() soon. */ - /* This is a little faster than failing here. */ - s->distance_code = 0x0fffffff; - } - } - } - } else { - int distval = s->distance_code - (int)s->num_direct_distance_codes; - if (distval >= 0) { - uint32_t nbits; - int postfix; - int offset; - if (s->distance_postfix_bits == 0) { - nbits = ((uint32_t)distval >> 1) + 1; - offset = ((2 + (distval & 1)) << nbits) - 4; - s->distance_code = (int)s->num_direct_distance_codes + - offset + (int)BrotliReadBits(br, nbits); - } else { - postfix = distval & s->distance_postfix_mask; - distval >>= s->distance_postfix_bits; - nbits = ((uint32_t)distval >> 1) + 1; - offset = ((2 + (distval & 1)) << nbits) - 4; - s->distance_code = (int)s->num_direct_distance_codes + - ((offset + (int)BrotliReadBits(br, nbits)) << - s->distance_postfix_bits) + postfix; - } - } - s->distance_code = s->distance_code - NUM_DISTANCE_SHORT_CODES + 1; - } -postReadDistance: - BROTLI_LOG_UINT(s->distance_code); - if (s->max_distance != s->max_backward_distance) { - if (pos < s->max_backward_distance_minus_custom_dict_size) { - s->max_distance = pos + s->custom_dict_size; - } else { - s->max_distance = s->max_backward_distance; - } - } - i = s->copy_length; - /* Apply copy of LZ77 back-reference, or static dictionary reference if - the distance is larger than the max LZ77 distance */ - if (s->distance_code > s->max_distance) { - if (i >= kBrotliMinDictionaryWordLength && - i <= kBrotliMaxDictionaryWordLength) { - int offset = kBrotliDictionaryOffsetsByLength[i]; - int word_id = s->distance_code - s->max_distance - 1; - uint32_t shift = kBrotliDictionarySizeBitsByLength[i]; - int mask = (int)BitMask(shift); - int word_idx = word_id & mask; - int transform_idx = word_id >> shift; - offset += word_idx * i; - if (transform_idx < kNumTransforms) { - const uint8_t* word = &kBrotliDictionary[offset]; - int len = i; - if (transform_idx == 0) { - memcpy(&s->ringbuffer[pos], word, (size_t)len); - } else { - len = TransformDictionaryWord( - &s->ringbuffer[pos], word, len, transform_idx); - } - pos += len; - s->meta_block_remaining_len -= len; - if (pos >= s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_POST_WRITE_1; - break; - } - } else { - BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", - pos, s->distance_code, i, - s->meta_block_remaining_len)); - result = BROTLI_FAILURE(); - break; - } - } else { - BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, s->distance_code, i, - s->meta_block_remaining_len)); - result = BROTLI_FAILURE(); - break; - } - } else { - const uint8_t *ringbuffer_end_minus_copy_length = - s->ringbuffer_end - i; - copy_src = &s->ringbuffer[(pos - s->distance_code) & - s->ringbuffer_mask]; - copy_dst = &s->ringbuffer[pos]; - /* update the recent distances cache */ - s->dist_rb[s->dist_rb_idx & 3] = s->distance_code; - ++s->dist_rb_idx; - s->meta_block_remaining_len -= i; - if (PREDICT_FALSE(s->meta_block_remaining_len < 0)) { - BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d " - "len: %d bytes left: %d\n", pos, s->distance_code, i, - s->meta_block_remaining_len)); - result = BROTLI_FAILURE(); - break; - } - /* There is 128+ bytes of slack in the ringbuffer allocation. - Also, we have 16 short codes, that make these 16 bytes irrelevant - in the ringbuffer. Let's copy over them as a first guess. - */ - memmove16(copy_dst, copy_src); - /* Now check if the copy extends over the ringbuffer end, - or if the copy overlaps with itself, if yes, do wrap-copy. */ - if (copy_src < copy_dst) { - if (copy_dst >= ringbuffer_end_minus_copy_length) { - goto postWrapCopy; - } - if (copy_src + i > copy_dst) { - goto postSelfintersecting; - } - } else { - if (copy_src >= ringbuffer_end_minus_copy_length) { - goto postWrapCopy; - } - if (copy_dst + i > copy_src) { - goto postSelfintersecting; - } - } - pos += i; - if (i > 16) { - if (i > 32) { - memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16)); - } else { - /* This branch covers about 45% cases. - Fixed size short copy allows more compiler optimizations. */ - memmove16(copy_dst + 16, copy_src + 16); - } - } - } - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } else { - goto CommandBegin; - } - postSelfintersecting: - while (--i >= 0) { - s->ringbuffer[pos] = - s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; - ++pos; - } - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } else { - goto CommandBegin; - } - postWrapCopy: - s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; - /* No break, go to next state */ + case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS: case BROTLI_STATE_COMMAND_POST_WRAP_COPY: - while (--i >= 0) { - s->ringbuffer[pos] = - s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask]; - ++pos; - if (pos == s->ringbuffer_size) { - s->to_write = s->ringbuffer_size; - s->partially_written = 0; - s->state = BROTLI_STATE_COMMAND_POST_WRITE_2; - break; - } - } - if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) { - if (s->meta_block_remaining_len <= 0) { - /* Next metablock, if any */ - s->state = BROTLI_STATE_METABLOCK_DONE; - break; - } else { - goto CommandBegin; - } + result = ProcessCommands(s); + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { + result = SafeProcessCommands(s); } break; case BROTLI_STATE_COMMAND_INNER_WRITE: case BROTLI_STATE_COMMAND_POST_WRITE_1: case BROTLI_STATE_COMMAND_POST_WRITE_2: -innerWrite: - result = WriteRingBuffer(output, s); + result = WriteRingBuffer(available_out, next_out, total_out, s); if (result != BROTLI_RESULT_SUCCESS) { break; } - pos -= s->ringbuffer_size; + s->pos -= s->ringbuffer_size; + s->rb_roundtrips++; s->max_distance = s->max_backward_distance; if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) { - memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)pos); + memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos); if (s->meta_block_remaining_len <= 0) { /* Next metablock, if any */ s->state = BROTLI_STATE_METABLOCK_DONE; - break; } else { - goto CommandBegin; + s->state = BROTLI_STATE_COMMAND_BEGIN; } + break; } else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) { s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY; } else { /* BROTLI_STATE_COMMAND_INNER_WRITE */ - if (i == 0) { + if (s->loop_counter == 0) { if (s->meta_block_remaining_len <= 0) { s->state = BROTLI_STATE_METABLOCK_DONE; - break; + } else { + s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS; } - goto postDecodeLiterals; + break; } s->state = BROTLI_STATE_COMMAND_INNER; } @@ -1675,30 +2283,26 @@ innerWrite: s->state = BROTLI_STATE_METABLOCK_BEGIN; break; } - s->to_write = pos; - s->partially_written = 0; + if (!BrotliJumpToByteBoundary(br)) { + result = BROTLI_FAILURE(); + } + if (s->buffer_length == 0) { + BrotliBitReaderUnload(br); + *available_in = br->avail_in; + *next_in = br->next_in; + } s->state = BROTLI_STATE_DONE; /* No break, continue to next state */ case BROTLI_STATE_DONE: if (s->ringbuffer != 0) { - result = WriteRingBuffer(output, s); + result = WriteRingBuffer(available_out, next_out, total_out, s); if (result != BROTLI_RESULT_SUCCESS) { break; } } - if (!BrotliJumpToByteBoundary(br)) { - result = BROTLI_FAILURE(); - } - if (!BrotliIsBitReaderOK(br)) { - /* The brotli input stream was too small, does not follow the spec. - NOTE: larger input is allowed, smaller not. */ - result = BROTLI_FAILURE(); - } return result; } } - s->pos = pos; - s->loop_counter = i; return result; } diff --git a/third_party/brotli/dec/decode.h b/third_party/brotli/dec/decode.h index cd3d124..78a156e 100644 --- a/third_party/brotli/dec/decode.h +++ b/third_party/brotli/dec/decode.h @@ -62,9 +62,6 @@ int BrotliDecompressedSize(size_t encoded_size, /* Decompresses the data in encoded_buffer into decoded_buffer, and sets */ /* *decoded_size to the decompressed length. */ -/* Returns 0 if there was either a bit stream error or memory allocation */ -/* error, and 1 otherwise. */ -/* If decoded size is zero, returns 1 and keeps decoded_buffer unchanged. */ BrotliResult BrotliDecompressBuffer(size_t encoded_size, const uint8_t* encoded_buffer, size_t* decoded_size, @@ -72,6 +69,7 @@ BrotliResult BrotliDecompressBuffer(size_t encoded_size, /* Same as above, but uses the specified input and output callbacks instead */ /* of reading from and writing to pre-allocated memory buffers. */ +/* DEPRECATED */ BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output); /* Same as above, but supports the caller to call the decoder repeatedly with @@ -99,6 +97,7 @@ BrotliResult BrotliDecompress(BrotliInput input, BrotliOutput output); it returning a smaller value than the amount of bytes to write always results in an error. */ +/* DEPRECATED */ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, int finish, BrotliState* s); @@ -129,6 +128,7 @@ BrotliResult BrotliDecompressStreaming(BrotliInput input, BrotliOutput output, *available_out yourself before a next call, e.g. to point to a new larger buffer. */ +/* DEPRECATED */ BrotliResult BrotliDecompressBufferStreaming(size_t* available_in, const uint8_t** next_in, int finish, @@ -137,6 +137,13 @@ BrotliResult BrotliDecompressBufferStreaming(size_t* available_in, size_t* total_out, BrotliState* s); +BrotliResult BrotliDecompressStream(size_t* available_in, + const uint8_t** next_in, + size_t* available_out, + uint8_t** next_out, + size_t* total_out, + BrotliState* s); + /* Fills the new state with a dictionary for LZ77, warming up the ringbuffer, e.g. for custom static dictionaries for data formats. Not to be confused with the built-in transformable dictionary of Brotli. @@ -151,10 +158,6 @@ void BrotliSetCustomDictionary( size_t size, const uint8_t* dict, BrotliState* s); -/* Escalate internal functions visibility; for testing purposes only. */ -void InverseMoveToFrontTransformForTesting( - uint8_t* v, uint32_t l, BrotliState* s); - #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif diff --git a/third_party/brotli/dec/huffman.c b/third_party/brotli/dec/huffman.c index d4ccbd9..0628c36 100644 --- a/third_party/brotli/dec/huffman.c +++ b/third_party/brotli/dec/huffman.c @@ -377,6 +377,7 @@ void BrotliHuffmanTreeGroupInit(HuffmanTreeGroup* group, uint32_t alphabet_size, void BrotliHuffmanTreeGroupRelease(HuffmanTreeGroup* group) { BROTLI_FREE(group->codes); + group->htrees = NULL; } #if defined(__cplusplus) || defined(c_plusplus) diff --git a/third_party/brotli/dec/port.h b/third_party/brotli/dec/port.h index bf33242..f8fc4a8 100644 --- a/third_party/brotli/dec/port.h +++ b/third_party/brotli/dec/port.h @@ -19,8 +19,10 @@ * BROTLI_BUILD_32_BIT disables 64-bit optimizations * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations - * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations + * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations + * BROTLI_BUILD_MODERN_COMPILER forces to use modern compilers built-ins, + features and attributes * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned read and overlapping memcpy; this reduces decompression speed by 5% * BROTLI_DEBUG dumps file name and line number when decoder detects stream @@ -46,6 +48,59 @@ #define __has_feature(x) 0 #endif +#if defined(__sparc) +#define BROTLI_TARGET_SPARC +#endif + +#if defined(__arm__) || defined(__thumb__) || \ + defined(_M_ARM) || defined(_M_ARMT) +#define BROTLI_TARGET_ARM +#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) || \ + (defined(M_ARM) && (M_ARM >= 7)) +#define BROTLI_TARGET_ARMV7 +#endif /* ARMv7 */ +#if defined(__aarch64__) +#define BROTLI_TARGET_ARMV8 +#endif /* ARMv8 */ +#endif /* ARM */ + +#if defined(__x86_64__) || defined(_M_X64) +#define BROTLI_TARGET_X64 +#endif + +#if defined(__PPC64__) +#define BROTLI_TARGET_POWERPC64 +#endif + +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define BROTLI_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +#define BROTLI_GCC_VERSION 0 +#endif + +#if defined(__ICC) +#define BROTLI_ICC_VERSION __ICC +#else +#define BROTLI_ICC_VERSION 0 +#endif + +#if defined(BROTLI_BUILD_MODERN_COMPILER) +#define BROTLI_MODERN_COMPILER 1 +#elif (BROTLI_GCC_VERSION > 300) || (BROTLI_ICC_VERSION >= 1600) +#define BROTLI_MODERN_COMPILER 1 +#else +#define BROTLI_MODERN_COMPILER 0 +#endif + +/* SPARC and ARMv6 don't support unaligned read. + Choose portable build for them. */ +#if !defined(BROTLI_BUILD_PORTABLE) +#if defined(BROTLI_TARGET_SPARC) || \ + (defined(BROTLI_TARGET_ARM) && !defined(BROTLI_TARGET_ARMV7)) +#define BROTLI_BUILD_PORTABLE +#endif /* SPARK or ARMv6 */ +#endif /* portable build */ + #ifdef BROTLI_BUILD_PORTABLE #define BROTLI_ALIGNED_READ 1 #define BROTLI_SAFE_MEMMOVE 1 @@ -73,8 +128,7 @@ OR: } */ -#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || \ - (defined(__llvm__) && __has_builtin(__builtin_expect)) +#if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_expect) #define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) #define PREDICT_FALSE(x) (__builtin_expect(x, 0)) #else @@ -83,15 +137,13 @@ OR: #endif /* IS_CONSTANT macros returns true for compile-time constant expressions. */ -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \ - (defined(__llvm__) && __has_builtin(__builtin_constant_p)) +#if BROTLI_MODERN_COMPILER || __has_builtin(__builtin_constant_p) #define IS_CONSTANT(x) __builtin_constant_p(x) #else #define IS_CONSTANT(x) 0 #endif -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 0) || \ - (defined(__llvm__) && __has_attribute(always_inline)) +#if BROTLI_MODERN_COMPILER || __has_attribute(always_inline) #define ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) #else #define ATTRIBUTE_ALWAYS_INLINE @@ -118,8 +170,8 @@ OR: #define BROTLI_64_BITS 1 #elif defined(BROTLI_BUILD_32_BIT) #define BROTLI_64_BITS 0 -#elif defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || \ - defined(__PPC64__) +#elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8) || \ + defined(BROTLI_TARGET_POWERPC64) #define BROTLI_64_BITS 1 #else #define BROTLI_64_BITS 0 @@ -150,8 +202,7 @@ OR: #define BROTLI_LITTLE_ENDIAN 0 #endif -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || \ - (defined(__llvm__) && __has_attribute(noinline)) +#if BROTLI_MODERN_COMPILER || __has_attribute(noinline) #define BROTLI_NOINLINE __attribute__ ((noinline)) #else #define BROTLI_NOINLINE @@ -169,8 +220,8 @@ OR: if ((N & 4) != 0) {X; X; X; X;} \ } -#if (__GNUC__ > 2) || defined(__llvm__) -#if (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) +#if BROTLI_MODERN_COMPILER || defined(__llvm__) +#if defined(BROTLI_TARGET_ARMV7) static BROTLI_INLINE unsigned BrotliRBit(unsigned input) { unsigned output; __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input)); @@ -180,6 +231,12 @@ static BROTLI_INLINE unsigned BrotliRBit(unsigned input) { #endif /* armv7 */ #endif /* gcc || clang */ +#if defined(BROTLI_TARGET_ARM) +#define BROTLI_HAS_UBFX 1 +#else +#define BROTLI_HAS_UBFX 0 +#endif + #define BROTLI_FREE(X) { \ free(X); \ X = NULL; \ diff --git a/third_party/brotli/dec/prefix.h b/third_party/brotli/dec/prefix.h index 0d77f6e..91e43e92 100644 --- a/third_party/brotli/dec/prefix.h +++ b/third_party/brotli/dec/prefix.h @@ -23,7 +23,7 @@ /* Represents the range of values belonging to a prefix code: */ /* [offset, offset + 2^nbits) */ struct PrefixCodeRange { - int16_t offset; + uint16_t offset; uint8_t nbits; }; diff --git a/third_party/brotli/dec/state.c b/third_party/brotli/dec/state.c index d32dfd3..f4f239a 100644 --- a/third_party/brotli/dec/state.c +++ b/third_party/brotli/dec/state.c @@ -24,6 +24,7 @@ extern "C" { #endif void BrotliStateInit(BrotliState* s) { + BrotliInitBitReader(&s->br); s->state = BROTLI_STATE_UNINITED; s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE; s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE; @@ -31,9 +32,13 @@ void BrotliStateInit(BrotliState* s) { s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE; s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE; s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE; + s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE; + s->buffer_length = 0; s->loop_counter = 0; s->pos = 0; + s->rb_roundtrips = 0; + s->partial_pos_out = 0; s->block_type_trees = NULL; s->block_len_trees = NULL; @@ -45,6 +50,8 @@ void BrotliStateInit(BrotliState* s) { s->context_map_slice = NULL; s->dist_context_map_slice = NULL; + s->sub_loop_counter = 0; + s->literal_hgroup.codes = NULL; s->literal_hgroup.htrees = NULL; s->insert_copy_hgroup.codes = NULL; @@ -71,13 +78,20 @@ void BrotliStateInit(BrotliState* s) { s->symbol_lists = &s->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1]; s->mtf_upper_bound = 255; + + s->legacy_input_buffer = 0; + s->legacy_output_buffer = 0; + s->legacy_input_len = 0; + s->legacy_output_len = 0; + s->legacy_input_pos = 0; + s->legacy_output_pos = 0; } void BrotliStateMetablockBegin(BrotliState* s) { s->meta_block_remaining_len = 0; - s->block_length[0] = 1 << 28; - s->block_length[1] = 1 << 28; - s->block_length[2] = 1 << 28; + s->block_length[0] = 1U << 28; + s->block_length[1] = 1U << 28; + s->block_length[2] = 1U << 28; s->num_block_types[0] = 1; s->num_block_types[1] = 1; s->num_block_types[2] = 1; @@ -113,27 +127,27 @@ void BrotliStateCleanupAfterMetablock(BrotliState* s) { BrotliHuffmanTreeGroupRelease(&s->literal_hgroup); BrotliHuffmanTreeGroupRelease(&s->insert_copy_hgroup); BrotliHuffmanTreeGroupRelease(&s->distance_hgroup); - s->literal_hgroup.codes = NULL; - s->literal_hgroup.htrees = NULL; - s->insert_copy_hgroup.codes = NULL; - s->insert_copy_hgroup.htrees = NULL; - s->distance_hgroup.codes = NULL; - s->distance_hgroup.htrees = NULL; } void BrotliStateCleanup(BrotliState* s) { - BROTLI_FREE(s->context_modes); - BROTLI_FREE(s->context_map); - BROTLI_FREE(s->dist_context_map); - - BrotliHuffmanTreeGroupRelease(&s->literal_hgroup); - BrotliHuffmanTreeGroupRelease(&s->insert_copy_hgroup); - BrotliHuffmanTreeGroupRelease(&s->distance_hgroup); + BrotliStateCleanupAfterMetablock(s); BROTLI_FREE(s->ringbuffer); BROTLI_FREE(s->block_type_trees); + BROTLI_FREE(s->legacy_input_buffer); + BROTLI_FREE(s->legacy_output_buffer); } +int BrotliStateIsStreamStart(const BrotliState* s) { + return (s->state == BROTLI_STATE_UNINITED && + BrotliGetAvailableBits(&s->br) == 0); +} + +int BrotliStateIsStreamEnd(const BrotliState* s) { + return s->state == BROTLI_STATE_DONE; +} + + #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif diff --git a/third_party/brotli/dec/state.h b/third_party/brotli/dec/state.h index 241ee6c..0d9329b 100644 --- a/third_party/brotli/dec/state.h +++ b/third_party/brotli/dec/state.h @@ -21,7 +21,6 @@ #include <stdio.h> #include "./bit_reader.h" #include "./huffman.h" -#include "./streams.h" #include "./types.h" #if defined(__cplusplus) || defined(c_plusplus) @@ -30,19 +29,20 @@ extern "C" { typedef enum { BROTLI_STATE_UNINITED, - BROTLI_STATE_BITREADER_WARMUP, BROTLI_STATE_METABLOCK_BEGIN, BROTLI_STATE_METABLOCK_HEADER, + BROTLI_STATE_METABLOCK_HEADER_2, BROTLI_STATE_CONTEXT_MODES, BROTLI_STATE_COMMAND_BEGIN, BROTLI_STATE_COMMAND_INNER, + BROTLI_STATE_COMMAND_POST_DECODE_LITERALS, + BROTLI_STATE_COMMAND_POST_WRAP_COPY, BROTLI_STATE_UNCOMPRESSED, BROTLI_STATE_METADATA, BROTLI_STATE_COMMAND_INNER_WRITE, BROTLI_STATE_METABLOCK_DONE, BROTLI_STATE_COMMAND_POST_WRITE_1, BROTLI_STATE_COMMAND_POST_WRITE_2, - BROTLI_STATE_COMMAND_POST_WRAP_COPY, BROTLI_STATE_HUFFMAN_CODE_0, BROTLI_STATE_HUFFMAN_CODE_1, BROTLI_STATE_HUFFMAN_CODE_2, @@ -66,8 +66,6 @@ typedef enum { typedef enum { BROTLI_STATE_UNCOMPRESSED_NONE, - BROTLI_STATE_UNCOMPRESSED_SHORT, - BROTLI_STATE_UNCOMPRESSED_COPY, BROTLI_STATE_UNCOMPRESSED_WRITE } BrotliRunningUncompressedState; @@ -80,11 +78,16 @@ typedef enum { BROTLI_STATE_CONTEXT_MAP_NONE, BROTLI_STATE_CONTEXT_MAP_READ_PREFIX, BROTLI_STATE_CONTEXT_MAP_HUFFMAN, - BROTLI_STATE_CONTEXT_MAP_DECODE + BROTLI_STATE_CONTEXT_MAP_DECODE, + BROTLI_STATE_CONTEXT_MAP_TRANSFORM } BrotliRunningContextMapState; typedef enum { BROTLI_STATE_HUFFMAN_NONE, + BROTLI_STATE_HUFFMAN_SIMPLE_SIZE, + BROTLI_STATE_HUFFMAN_SIMPLE_READ, + BROTLI_STATE_HUFFMAN_SIMPLE_BUILD, + BROTLI_STATE_HUFFMAN_COMPLEX, BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS } BrotliRunningHuffmanState; @@ -94,10 +97,23 @@ typedef enum { BROTLI_STATE_DECODE_UINT8_LONG } BrotliRunningDecodeUint8State; -typedef struct { +typedef enum { + BROTLI_STATE_READ_BLOCK_LENGTH_NONE, + BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX +} BrotliRunningReadBlockLengthState; + +struct BrotliStateStruct { BrotliRunningState state; - /* This counter is reused for several disjoint loops. */ BrotliBitReader br; + + /* Temporary storage for remaining input. */ + union { + uint64_t u64; + uint8_t u8[8]; + } buffer; + uint32_t buffer_length; + + /* This counter is reused for several disjoint loops. */ int loop_counter; int pos; int max_backward_distance; @@ -115,6 +131,8 @@ typedef struct { uint8_t* context_map_slice; uint8_t* dist_context_map_slice; + uint32_t sub_loop_counter; + /* This ring buffer holds a few past copy distances that will be used by */ /* some special distance codes. */ HuffmanTreeGroup literal_hgroup; @@ -127,7 +145,8 @@ typedef struct { int trivial_literal_context; int distance_context; int meta_block_remaining_len; - int block_length[3]; + uint32_t block_length_index; + uint32_t block_length[3]; uint32_t num_block_types[3]; uint32_t block_type_rb[6]; uint32_t distance_postfix_bits; @@ -138,16 +157,16 @@ typedef struct { HuffmanCode *literal_htree; uint8_t literal_htree_index; uint8_t dist_htree_index; - uint8_t repeat_code_len; - uint8_t prev_code_len; + uint32_t repeat_code_len; + uint32_t prev_code_len; int copy_length; int distance_code; /* For partial write operations */ - int to_write; - int partially_written; + size_t rb_roundtrips; /* How many times we went around the ringbuffer */ + size_t partial_pos_out; /* How much output to the user in total (<= rb) */ /* For ReadHuffmanCode */ uint32_t symbol; @@ -173,6 +192,7 @@ typedef struct { /* For DecodeContextMap */ uint32_t context_index; uint32_t max_run_length_prefix; + uint32_t code; HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_TABLE_SIZE]; /* For InverseMoveToFrontTransform */ @@ -191,6 +211,7 @@ typedef struct { BrotliRunningUncompressedState substate_uncompressed; BrotliRunningHuffmanState substate_huffman; BrotliRunningDecodeUint8State substate_decode_uint8; + BrotliRunningReadBlockLengthState substate_read_block_length; uint8_t is_last_metablock; uint8_t is_uncompressed; @@ -201,13 +222,32 @@ typedef struct { uint32_t num_literal_htrees; uint8_t* context_map; uint8_t* context_modes; -} BrotliState; + + uint8_t* legacy_input_buffer; + uint8_t* legacy_output_buffer; + size_t legacy_input_len; + size_t legacy_output_len; + size_t legacy_input_pos; + size_t legacy_output_pos; +}; + +typedef struct BrotliStateStruct BrotliState; void BrotliStateInit(BrotliState* s); void BrotliStateCleanup(BrotliState* s); void BrotliStateMetablockBegin(BrotliState* s); void BrotliStateCleanupAfterMetablock(BrotliState* s); + +/* Returns 1, if s is in a state where we have not read any input bytes yet, + and 0 otherwise */ +int BrotliStateIsStreamStart(const BrotliState* s); + +/* Returns 1, if s is in a state where we reached the end of the input and + produced all of the output, and 0 otherwise. */ +int BrotliStateIsStreamEnd(const BrotliState* s); + + #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ #endif diff --git a/third_party/brotli/dec/streams.c b/third_party/brotli/dec/streams.c index f7060a9..007c513 100644 --- a/third_party/brotli/dec/streams.c +++ b/third_party/brotli/dec/streams.c @@ -99,7 +99,7 @@ int BrotliNullOutputFunction(void* data , const uint8_t* buf, size_t count) { return (int)count; } -BrotliOutput BrotliNullOutput() { +BrotliOutput BrotliNullOutput(void) { BrotliOutput out; out.cb_ = BrotliNullOutputFunction; out.data_ = NULL; diff --git a/third_party/brotli/dec/streams.h b/third_party/brotli/dec/streams.h index decfa7e..99eb125 100644 --- a/third_party/brotli/dec/streams.h +++ b/third_party/brotli/dec/streams.h @@ -95,7 +95,7 @@ BrotliOutput BrotliFileOutput(FILE* f); /* Output callback that does nothing, always consumes the whole input. */ int BrotliNullOutputFunction(void* data, const uint8_t* buf, size_t count); -BrotliOutput BrotliNullOutput(); +BrotliOutput BrotliNullOutput(void); #if defined(__cplusplus) || defined(c_plusplus) } /* extern "C" */ diff --git a/third_party/brotli/dec/types.h b/third_party/brotli/dec/types.h index e7e5ab1..8a9cc4a 100644 --- a/third_party/brotli/dec/types.h +++ b/third_party/brotli/dec/types.h @@ -21,14 +21,14 @@ #include <stddef.h> /* for size_t */ #if defined(_MSC_VER) && (_MSC_VER < 1600) -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef signed short int16_t; -typedef unsigned short uint16_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef unsigned long long int uint64_t; -typedef long long int int64_t; +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; #else #include <stdint.h> #endif /* defined(_MSC_VER) && (_MSC_VER < 1600) */ |