Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 10 additions & 26 deletions src/dec/vp8l_dec.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,33 +394,17 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
num_htree_groups_max = group + 1;
}
}
// Check the validity of num_htree_groups_max. If it seems too big, use a
// smaller value for later. This will prevent big memory allocations to end
// up with a bad bitstream anyway.
// The value of 1000 is totally arbitrary. We know that num_htree_groups_max
// is smaller than (1 << 16) and should be smaller than the number of pixels
// (though the format allows it to be bigger).
if (num_htree_groups_max > 1000 || num_htree_groups_max > xsize * ysize) {
// Create a mapping from the used indices to the minimal set of used
// values [0, num_htree_groups)
mapping = (int*)WebPSafeMalloc(num_htree_groups_max, sizeof(*mapping));
if (mapping == NULL) {
VP8LSetError(dec, VP8_STATUS_OUT_OF_MEMORY);
goto Error;
}
// -1 means a value is unmapped, and therefore unused in the Huffman
// image.
WEBP_UNSAFE_MEMSET(mapping, 0xff,
num_htree_groups_max * sizeof(*mapping));
for (num_htree_groups = 0, i = 0; i < huffman_pixs; ++i) {
// Get the current mapping for the group and remap the Huffman image.
int* const mapped_group = &mapping[huffman_image[i]];
if (*mapped_group == -1) *mapped_group = num_htree_groups++;
huffman_image[i] = *mapped_group;
}
} else {
num_htree_groups = num_htree_groups_max;
// Check the validity of num_htree_groups_max. Sparse high group IDs would
// otherwise force parsing up to 65k Huffman tables (amplification). Fail
// closed instead of remapping and still walking the full index range.
// The value of 1000 matches the historical soft threshold and stays below
// the pixel count when the image is small.
if (num_htree_groups_max > 1000 ||
num_htree_groups_max > (uint64_t)xsize * ysize) {
VP8LSetError(dec, VP8_STATUS_BITSTREAM_ERROR);
goto Error;
}
num_htree_groups = num_htree_groups_max;
}

if (br->eos) goto Error;
Expand Down
4 changes: 3 additions & 1 deletion src/utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ extern "C" {
// This is the maximum memory amount that libwebp will ever try to allocate.
#ifndef WEBP_MAX_ALLOCABLE_MEMORY
#if SIZE_MAX > (1ULL << 34)
#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 34)
/* Cap single allocations to 1 GiB by default (was 16 GiB). Override at
* compile time if a larger budget is intentionally required. */
#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 30)
#else
// For 32-bit targets keep this below INT_MAX to avoid valgrind warnings.
#define WEBP_MAX_ALLOCABLE_MEMORY ((1ULL << 31) - (1 << 16))
Expand Down
6 changes: 4 additions & 2 deletions src/webp/format_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ typedef enum {
#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk.
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.

#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
/* Align decoder area with encoder WEBP_MAX_DIMENSION (16383) to prevent
* multi-GiB canvas allocations from crafted VP8X dimensions. */
#define MAX_IMAGE_AREA (16383ULL * 16383ULL)
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
#define MAX_DURATION (1 << 24) // maximum duration
#define MAX_POSITION_OFFSET (1 << 24) // maximum frame x/y offset
Expand Down