sierravmd: Do sanity checking of frame sizes

Limit the size to INT_MAX/2 (for simplicity) to be sure that
size + BYTES_PER_FRAME_RECORD won't overflow.

Also factorize other existing error return paths.

Reported-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable@libav.org
Signed-off-by: Martin Storsjö <martin@martin.st>
This commit is contained in:
Martin Storsjö 2013-09-11 22:56:55 +03:00
parent 342c43d154
commit 0ef1660a63
1 changed files with 15 additions and 7 deletions

View File

@ -88,7 +88,7 @@ static int vmd_read_header(AVFormatContext *s)
unsigned char *raw_frame_table; unsigned char *raw_frame_table;
int raw_frame_table_size; int raw_frame_table_size;
int64_t current_offset; int64_t current_offset;
int i, j; int i, j, ret;
unsigned int total_frames; unsigned int total_frames;
int64_t current_audio_pts = 0; int64_t current_audio_pts = 0;
unsigned char chunk[BYTES_PER_FRAME_RECORD]; unsigned char chunk[BYTES_PER_FRAME_RECORD];
@ -175,15 +175,13 @@ static int vmd_read_header(AVFormatContext *s)
raw_frame_table = av_malloc(raw_frame_table_size); raw_frame_table = av_malloc(raw_frame_table_size);
vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame)); vmd->frame_table = av_malloc((vmd->frame_count * vmd->frames_per_block + sound_buffers) * sizeof(vmd_frame));
if (!raw_frame_table || !vmd->frame_table) { if (!raw_frame_table || !vmd->frame_table) {
av_free(raw_frame_table); ret = AVERROR(ENOMEM);
av_free(vmd->frame_table); goto error;
return AVERROR(ENOMEM);
} }
if (avio_read(pb, raw_frame_table, raw_frame_table_size) != if (avio_read(pb, raw_frame_table, raw_frame_table_size) !=
raw_frame_table_size) { raw_frame_table_size) {
av_free(raw_frame_table); ret = AVERROR(EIO);
av_free(vmd->frame_table); goto error;
return AVERROR(EIO);
} }
total_frames = 0; total_frames = 0;
@ -199,6 +197,11 @@ static int vmd_read_header(AVFormatContext *s)
avio_read(pb, chunk, BYTES_PER_FRAME_RECORD); avio_read(pb, chunk, BYTES_PER_FRAME_RECORD);
type = chunk[0]; type = chunk[0];
size = AV_RL32(&chunk[2]); size = AV_RL32(&chunk[2]);
if (size > INT_MAX / 2) {
av_log(s, AV_LOG_ERROR, "Invalid frame size\n");
ret = AVERROR_INVALIDDATA;
goto error;
}
if(!size && type != 1) if(!size && type != 1)
continue; continue;
switch(type) { switch(type) {
@ -235,6 +238,11 @@ static int vmd_read_header(AVFormatContext *s)
vmd->frame_count = total_frames; vmd->frame_count = total_frames;
return 0; return 0;
error:
av_free(raw_frame_table);
av_free(vmd->frame_table);
return ret;
} }
static int vmd_read_packet(AVFormatContext *s, static int vmd_read_packet(AVFormatContext *s,