mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 04:18:26 +01:00
Stop indefinite recursion for Huffman Image.
Ensure that the lossless bit-stream doesn't allow for such cases and safe-gaurd decoder against indefinite recursion. Change-Id: Ia6d7f519291de8739f79a977a5800982872aae71
This commit is contained in:
parent
814a063925
commit
70eb2bd687
@ -302,7 +302,7 @@ static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
|
||||
}
|
||||
|
||||
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int color_cache_bits) {
|
||||
int color_cache_bits, int allow_recursion) {
|
||||
int i, j;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
VP8LMetadata* const hdr = &dec->hdr_;
|
||||
@ -310,12 +310,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
HTreeGroup* htree_groups = NULL;
|
||||
int num_htree_groups = 1;
|
||||
|
||||
if (VP8LReadBits(br, 1)) { // use meta Huffman codes
|
||||
if (allow_recursion && VP8LReadBits(br, 1)) {
|
||||
// use meta Huffman codes.
|
||||
const int huffman_precision = VP8LReadBits(br, 3) + 2;
|
||||
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
|
||||
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
|
||||
const int huffman_pixs = huffman_xsize * huffman_ysize;
|
||||
|
||||
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
|
||||
&huffman_image)) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
@ -862,7 +862,7 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
|
||||
// Read the Huffman codes (may recurse).
|
||||
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
|
||||
color_cache_bits);
|
||||
color_cache_bits, is_level0);
|
||||
if (!ok) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
goto End;
|
||||
|
@ -33,6 +33,10 @@ extern "C" {
|
||||
#define MIN_HISTO_BITS 2
|
||||
#define MAX_HISTO_BITS 9
|
||||
|
||||
// NO_HISTO_BITS needs to be large enough so that all bits in the image
|
||||
// size are thrown away by shifting.
|
||||
#define NO_HISTO_BITS (VP8L_IMAGE_SIZE_BITS + 1)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Palette
|
||||
|
||||
@ -442,10 +446,11 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
int cache_bits, int histogram_bits) {
|
||||
int i;
|
||||
int ok = 0;
|
||||
int write_histogram_image;
|
||||
const int use_2d_locality = 1;
|
||||
const int use_color_cache = (cache_bits > 0);
|
||||
const int histogram_image_xysize =
|
||||
(histogram_bits == NO_HISTO_BITS) ?
|
||||
1 :
|
||||
VP8LSubSampleSize(width, histogram_bits) *
|
||||
VP8LSubSampleSize(height, histogram_bits);
|
||||
VP8LHistogramSet* histogram_image =
|
||||
@ -456,7 +461,8 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
VP8LBackwardRefs refs;
|
||||
uint16_t* const histogram_symbols =
|
||||
(uint16_t*)malloc(histogram_image_xysize * sizeof(*histogram_symbols));
|
||||
|
||||
assert((histogram_bits >= 2 && histogram_bits <= 9) ||
|
||||
histogram_bits == NO_HISTO_BITS);
|
||||
if (histogram_image == NULL || histogram_symbols == NULL) goto Error;
|
||||
|
||||
// Calculate backward references from ARGB image.
|
||||
@ -488,7 +494,8 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
}
|
||||
|
||||
// Huffman image + meta huffman.
|
||||
write_histogram_image = (histogram_image_size > 1);
|
||||
if (histogram_bits != NO_HISTO_BITS) {
|
||||
const int write_histogram_image = (histogram_image_size > 1);
|
||||
VP8LWriteBits(bw, 1, write_histogram_image);
|
||||
if (write_histogram_image) {
|
||||
uint32_t* const histogram_argb =
|
||||
@ -504,15 +511,15 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
||||
}
|
||||
histogram_image_size = max_index;
|
||||
|
||||
assert(histogram_bits >= 2);
|
||||
VP8LWriteBits(bw, 3, histogram_bits - 2);
|
||||
ok = EncodeImageInternal(bw, histogram_argb,
|
||||
VP8LSubSampleSize(width, histogram_bits),
|
||||
VP8LSubSampleSize(height, histogram_bits),
|
||||
quality, 0, 0);
|
||||
quality, 0, NO_HISTO_BITS);
|
||||
free(histogram_argb);
|
||||
if (!ok) goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
// Store Huffman codes.
|
||||
for (i = 0; i < 5 * histogram_image_size; ++i) {
|
||||
@ -601,7 +608,8 @@ static int ApplyPredictFilter(const VP8LEncoder* const enc,
|
||||
assert(pred_bits >= 2);
|
||||
VP8LWriteBits(bw, 3, pred_bits - 2);
|
||||
if (!EncodeImageInternal(bw, enc->transform_data_,
|
||||
transform_width, transform_height, quality, 0, 0)) {
|
||||
transform_width, transform_height, quality, 0,
|
||||
NO_HISTO_BITS)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -622,7 +630,8 @@ static int ApplyCrossColorFilter(const VP8LEncoder* const enc,
|
||||
assert(ccolor_transform_bits >= 2);
|
||||
VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
|
||||
if (!EncodeImageInternal(bw, enc->transform_data_,
|
||||
transform_width, transform_height, quality, 0, 0)) {
|
||||
transform_width, transform_height, quality, 0,
|
||||
NO_HISTO_BITS)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -786,7 +795,8 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw,
|
||||
for (i = palette_size - 1; i >= 1; --i) {
|
||||
palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
|
||||
}
|
||||
if (!EncodeImageInternal(bw, palette, palette_size, 1, quality, 0, 0)) {
|
||||
if (!EncodeImageInternal(bw, palette, palette_size, 1, quality, 0,
|
||||
NO_HISTO_BITS)) {
|
||||
err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
|
||||
goto Error;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user