muxread,ChunkVerifyAndAssign: validate chunk_size

before accounting for padding which might overflow if chunk_size is >
MAX_CHUNK_PAYLOAD.

BUG=webp:387,webp:388,webp:512

Change-Id: I3985b8817ed4faaec0629102c5333c228a0e9c98
(cherry picked from commit be738c6d39)
(cherry picked from commit 6f643f2417)
This commit is contained in:
James Zern 2018-06-21 01:13:36 +00:00
parent 12669892f6
commit 47768596f6
2 changed files with 10 additions and 3 deletions

View File

@ -14,6 +14,7 @@
#ifndef WEBP_MUX_MUXI_H_ #ifndef WEBP_MUX_MUXI_H_
#define WEBP_MUX_MUXI_H_ #define WEBP_MUX_MUXI_H_
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include "src/dec/vp8i_dec.h" #include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h" #include "src/dec/vp8li_dec.h"
@ -143,13 +144,13 @@ void ChunkListDelete(WebPChunk** const chunk_list);
// Returns size of the chunk including chunk header and padding byte (if any). // Returns size of the chunk including chunk header and padding byte (if any).
static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) { static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
assert(chunk_size <= MAX_CHUNK_PAYLOAD);
return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U); return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
} }
// Size of a chunk including header and padding. // Size of a chunk including header and padding.
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) { static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
const size_t data_size = chunk->data_.size; const size_t data_size = chunk->data_.size;
assert(data_size < MAX_CHUNK_PAYLOAD);
return SizeWithPadding(data_size); return SizeWithPadding(data_size);
} }

View File

@ -59,6 +59,7 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
// Sanity checks. // Sanity checks.
if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA; if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
chunk_size = GetLE32(data + TAG_SIZE); chunk_size = GetLE32(data + TAG_SIZE);
if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA;
{ {
const size_t chunk_disk_size = SizeWithPadding(chunk_size); const size_t chunk_disk_size = SizeWithPadding(chunk_size);
@ -203,9 +204,14 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
goto Err; // First chunk should be VP8, VP8L or VP8X. goto Err; // First chunk should be VP8, VP8L or VP8X.
} }
riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE)); riff_size = GetLE32(data + TAG_SIZE);
if (riff_size > MAX_CHUNK_PAYLOAD) goto Err;
// Note this padding is historical and differs from demux.c which does not
// pad the file size.
riff_size = SizeWithPadding(riff_size);
if (riff_size < CHUNK_HEADER_SIZE) goto Err; if (riff_size < CHUNK_HEADER_SIZE) goto Err;
if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) goto Err; if (riff_size > size) goto Err;
// There's no point in reading past the end of the RIFF chunk. // There's no point in reading past the end of the RIFF chunk.
if (size > riff_size + CHUNK_HEADER_SIZE) { if (size > riff_size + CHUNK_HEADER_SIZE) {
size = riff_size + CHUNK_HEADER_SIZE; size = riff_size + CHUNK_HEADER_SIZE;