From 09bcc1f710ea65dc158639479288fb1908ff0c53 Mon Sep 17 00:00:00 2001 From: "Timothy B. Terriberry" Date: Tue, 19 Oct 2010 15:40:46 -0700 Subject: [PATCH] Improve handling of invalid frames. The code was not checking for frame sizes smaller than 3 bytes, and the partition size checks might have failed if the input buffer was within 16MB of the top of the heap. In addition, the reference count on the current frame buffer was not being decremented on error, so after a small number of errors, no new frame buffer could be found and it would run off the list of them. Change-Id: I0c60dba6adb1e2a29df39754f72a56ab6c776b46 --- vp8/decoder/decodframe.c | 9 ++++++--- vp8/decoder/onyxd_if.c | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index efe0ad8..2d81d61 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -462,7 +462,7 @@ static void setup_token_decoder(VP8D_COMP *pbi, partition_size = user_data_end - partition; } - if (partition + partition_size > user_data_end) + if (user_data_end - partition < partition_size) vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet or corrupt partition " "%d length", i + 1); @@ -564,12 +564,15 @@ int vp8_decode_frame(VP8D_COMP *pbi) MACROBLOCKD *const xd = & pbi->mb; const unsigned char *data = (const unsigned char *)pbi->Source; const unsigned char *const data_end = data + pbi->source_sz; - int first_partition_length_in_bytes; + unsigned int first_partition_length_in_bytes; int mb_row; int i, j, k, l; const int *const mb_feature_data_bits = vp8_mb_feature_data_bits; + if (data_end - data < 3) + vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, + "Truncated packet"); pc->frame_type = (FRAME_TYPE)(data[0] & 1); pc->version = (data[0] >> 1) & 7; pc->show_frame = (data[0] >> 4) & 1; @@ -577,7 +580,7 @@ int vp8_decode_frame(VP8D_COMP *pbi) (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5; data += 3; - if (data + first_partition_length_in_bytes > data_end) + if (data_end - data < first_partition_length_in_bytes) vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet or corrupt partition 0 length"); vp8_setup_version(pc); diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c index 7d716b0..884c38d 100644 --- a/vp8/decoder/onyxd_if.c +++ b/vp8/decoder/onyxd_if.c @@ -327,9 +327,13 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign pbi->common.error.error_code = VPX_CODEC_OK; + cm->new_fb_idx = get_free_fb (cm); + if (setjmp(pbi->common.error.jmp)) { pbi->common.error.setjmp = 0; + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; return -1; } @@ -345,8 +349,6 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign pbi->Source = source; pbi->source_sz = size; - cm->new_fb_idx = get_free_fb (cm); - retcode = vp8_decode_frame(pbi); if (retcode < 0) @@ -356,6 +358,8 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign #endif pbi->common.error.error_code = VPX_CODEC_ERROR; pbi->common.error.setjmp = 0; + if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0) + cm->fb_idx_ref_cnt[cm->new_fb_idx]--; return retcode; } -- 2.7.4