mirror of
https://github.com/google/brotli.git
synced 2026-07-08 17:56:58 +00:00
Detect and report invalid stream earlier.
PiperOrigin-RevId: 876198329
This commit is contained in:
committed by
Copybara-Service
parent
34f020fa9d
commit
0ed4268a44
@@ -1176,7 +1176,7 @@ static BrotliDecoderErrorCode DecodeContextMap(brotli_reg_t context_map_size,
|
||||
|
||||
/* Decodes a command or literal and updates block type ring-buffer.
|
||||
Reads 3..54 bits. */
|
||||
static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
|
||||
static BROTLI_INLINE BrotliDecoderErrorCode DecodeBlockTypeAndLength(
|
||||
int safe, BrotliDecoderState* s, int tree_type) {
|
||||
brotli_reg_t max_block_type = s->num_block_types[tree_type];
|
||||
const HuffmanCode* type_tree = &s->block_type_trees[
|
||||
@@ -1187,7 +1187,7 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
|
||||
brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];
|
||||
brotli_reg_t block_type;
|
||||
if (max_block_type <= 1) {
|
||||
return BROTLI_FALSE;
|
||||
return BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH;
|
||||
}
|
||||
|
||||
/* Read 0..15 + 3..39 bits. */
|
||||
@@ -1197,11 +1197,13 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
|
||||
} else {
|
||||
BrotliBitReaderState memento;
|
||||
BrotliBitReaderSaveState(br, &memento);
|
||||
if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;
|
||||
if (!SafeReadSymbol(type_tree, br, &block_type)) {
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
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 BROTLI_FALSE;
|
||||
return BROTLI_DECODER_NEEDS_MORE_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1217,7 +1219,7 @@ static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
|
||||
}
|
||||
ringbuffer[0] = ringbuffer[1];
|
||||
ringbuffer[1] = block_type;
|
||||
return BROTLI_TRUE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(
|
||||
@@ -1254,59 +1256,65 @@ static BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {
|
||||
|
||||
/* Decodes the block type and updates the state for literal context.
|
||||
Reads 3..54 bits. */
|
||||
static BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(
|
||||
static BROTLI_INLINE BrotliDecoderErrorCode DecodeLiteralBlockSwitchInternal(
|
||||
int safe, BrotliDecoderState* s) {
|
||||
if (!DecodeBlockTypeAndLength(safe, s, 0)) {
|
||||
return BROTLI_FALSE;
|
||||
BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 0);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
PrepareLiteralDecoding(s);
|
||||
return BROTLI_TRUE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
|
||||
DecodeLiteralBlockSwitchInternal(0, s);
|
||||
static BROTLI_NOINLINE BrotliDecoderErrorCode
|
||||
DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
|
||||
return DecodeLiteralBlockSwitchInternal(0, s);
|
||||
}
|
||||
|
||||
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(
|
||||
static BROTLI_NOINLINE BrotliDecoderErrorCode SafeDecodeLiteralBlockSwitch(
|
||||
BrotliDecoderState* s) {
|
||||
return DecodeLiteralBlockSwitchInternal(1, s);
|
||||
}
|
||||
|
||||
/* Block switch for insert/copy length.
|
||||
Reads 3..54 bits. */
|
||||
static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(
|
||||
static BROTLI_INLINE BrotliDecoderErrorCode DecodeCommandBlockSwitchInternal(
|
||||
int safe, BrotliDecoderState* s) {
|
||||
if (!DecodeBlockTypeAndLength(safe, s, 1)) {
|
||||
return BROTLI_FALSE;
|
||||
BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 1);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];
|
||||
return BROTLI_TRUE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {
|
||||
DecodeCommandBlockSwitchInternal(0, s);
|
||||
static BROTLI_NOINLINE BrotliDecoderErrorCode
|
||||
DecodeCommandBlockSwitch(BrotliDecoderState* s) {
|
||||
return DecodeCommandBlockSwitchInternal(0, s);
|
||||
}
|
||||
|
||||
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(
|
||||
BrotliDecoderState* s) {
|
||||
static BROTLI_NOINLINE BrotliDecoderErrorCode
|
||||
SafeDecodeCommandBlockSwitch(BrotliDecoderState* s) {
|
||||
return DecodeCommandBlockSwitchInternal(1, s);
|
||||
}
|
||||
|
||||
/* Block switch for distance codes.
|
||||
Reads 3..54 bits. */
|
||||
static BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(
|
||||
static BROTLI_INLINE BrotliDecoderErrorCode DecodeDistanceBlockSwitchInternal(
|
||||
int safe, BrotliDecoderState* s) {
|
||||
if (!DecodeBlockTypeAndLength(safe, s, 2)) {
|
||||
return BROTLI_FALSE;
|
||||
BrotliDecoderErrorCode result = DecodeBlockTypeAndLength(safe, s, 2);
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
s->dist_context_map_slice = s->dist_context_map +
|
||||
(s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);
|
||||
s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
|
||||
return BROTLI_TRUE;
|
||||
return BROTLI_DECODER_SUCCESS;
|
||||
}
|
||||
|
||||
static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
|
||||
DecodeDistanceBlockSwitchInternal(0, s);
|
||||
static BROTLI_NOINLINE BrotliDecoderErrorCode
|
||||
DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
|
||||
return DecodeDistanceBlockSwitchInternal(0, s);
|
||||
}
|
||||
|
||||
static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(
|
||||
@@ -1940,6 +1948,9 @@ static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
|
||||
return BrotliCheckInputAmount(br);
|
||||
}
|
||||
|
||||
/* NB: METHOD should return BROTLI_FALSE only in case there is not enough input;
|
||||
in case of "unsafe" execution, when input is guaranteed to be sufficient,
|
||||
result is ignored. */
|
||||
#define BROTLI_SAFE(METHOD) \
|
||||
{ \
|
||||
if (safe) { \
|
||||
@@ -1952,6 +1963,22 @@ static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
|
||||
} \
|
||||
}
|
||||
|
||||
/* NB: METHOD should return BROTLI_DECODER_SUCCESS, BROTLI_DECODER_ERROR_*, or
|
||||
BROTLI_DECODER_NEEDS_MORE_INPUT; the later two break the processing. */
|
||||
#define BROTLI_SAFE_WITH_STATUS(METHOD) \
|
||||
{ \
|
||||
BrotliDecoderErrorCode status; \
|
||||
if (safe) { \
|
||||
status = Safe##METHOD; \
|
||||
} else { \
|
||||
status = METHOD; \
|
||||
} \
|
||||
if (status != BROTLI_DECODER_SUCCESS) { \
|
||||
result = status; \
|
||||
goto saveStateAndReturn; \
|
||||
} \
|
||||
}
|
||||
|
||||
static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
|
||||
int safe, BrotliDecoderState* s) {
|
||||
int pos = s->pos;
|
||||
@@ -1991,7 +2018,7 @@ CommandBegin:
|
||||
goto saveStateAndReturn;
|
||||
}
|
||||
if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {
|
||||
BROTLI_SAFE(DecodeCommandBlockSwitch(s));
|
||||
BROTLI_SAFE_WITH_STATUS(DecodeCommandBlockSwitch(s));
|
||||
goto CommandBegin;
|
||||
}
|
||||
/* Read the insert/copy length in the command. */
|
||||
@@ -2136,7 +2163,7 @@ CommandPostDecodeLiterals:
|
||||
} else {
|
||||
/* Read distance code in the command, unless it was implicitly zero. */
|
||||
if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {
|
||||
BROTLI_SAFE(DecodeDistanceBlockSwitch(s));
|
||||
BROTLI_SAFE_WITH_STATUS(DecodeDistanceBlockSwitch(s));
|
||||
}
|
||||
BROTLI_SAFE(ReadDistance(s, br));
|
||||
}
|
||||
@@ -2330,7 +2357,7 @@ CommandPostWrapCopy:
|
||||
}
|
||||
|
||||
NextLiteralBlock:
|
||||
BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
|
||||
BROTLI_SAFE_WITH_STATUS(DecodeLiteralBlockSwitch(s));
|
||||
goto CommandInner;
|
||||
|
||||
saveStateAndReturn:
|
||||
@@ -2552,6 +2579,8 @@ BrotliDecoderResult BrotliDecoderDecompressStream(
|
||||
if (result != BROTLI_DECODER_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
BROTLI_DCHECK(s->meta_block_remaining_len <=
|
||||
(int)BROTLI_BLOCK_SIZE_CAP);
|
||||
BROTLI_LOG_UINT(s->is_last_metablock);
|
||||
BROTLI_LOG_UINT(s->meta_block_remaining_len);
|
||||
BROTLI_LOG_UINT(s->is_metadata);
|
||||
|
||||
@@ -85,9 +85,7 @@ typedef enum {
|
||||
BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \
|
||||
\
|
||||
/* -17 code is reserved */ \
|
||||
\
|
||||
BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_SWITCH, -17) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \
|
||||
BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \
|
||||
|
||||
Reference in New Issue
Block a user