From 494cfacdb9ba3f0549e37f76b3a2f86a7aeeac3c Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sun, 11 Sep 2011 19:17:45 +0200 Subject: [PATCH 01/10] vmd: fix segfaults on corruped streams Signed-off-by: Janne Grunau Signed-off-by: Reinhard Tartler --- libavcodec/vmdav.c | 104 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 24 deletions(-) diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index d258252d95..500adcb354 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -72,9 +72,11 @@ typedef struct VmdVideoContext { #define QUEUE_SIZE 0x1000 #define QUEUE_MASK 0x0FFF -static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_len) +static void lz_unpack(const unsigned char *src, int src_len, + unsigned char *dest, int dest_len) { const unsigned char *s; + unsigned int s_len; unsigned char *d; unsigned char *d_end; unsigned char queue[QUEUE_SIZE]; @@ -87,13 +89,16 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le unsigned int i, j; s = src; + s_len = src_len; d = dest; d_end = d + dest_len; dataleft = AV_RL32(s); - s += 4; + s += 4; s_len -= 4; memset(queue, 0x20, QUEUE_SIZE); + if (s_len < 4) + return; if (AV_RL32(s) == 0x56781234) { - s += 4; + s += 4; s_len -= 4; qpos = 0x111; speclen = 0xF + 3; } else { @@ -101,32 +106,41 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le speclen = 100; /* no speclen */ } - while (dataleft > 0) { - tag = *s++; + while (dataleft > 0 && s_len > 0) { + tag = *s++; s_len--; if ((tag == 0xFF) && (dataleft > 8)) { - if (d + 8 > d_end) + if (d + 8 > d_end || s_len < 8) return; for (i = 0; i < 8; i++) { queue[qpos++] = *d++ = *s++; qpos &= QUEUE_MASK; } + s_len -= 8; dataleft -= 8; } else { for (i = 0; i < 8; i++) { if (dataleft == 0) break; if (tag & 0x01) { - if (d + 1 > d_end) + if (d + 1 > d_end || s_len < 1) return; queue[qpos++] = *d++ = *s++; qpos &= QUEUE_MASK; dataleft--; + s_len--; } else { + if (s_len < 2) + return; chainofs = *s++; chainofs |= ((*s & 0xF0) << 4); chainlen = (*s++ & 0x0F) + 3; - if (chainlen == speclen) + s_len -= 2; + if (chainlen == speclen) { + if (s_len < 1) + return; chainlen = *s++ + 0xF + 3; + s_len--; + } if (d + chainlen > d_end) return; for (j = 0; j < chainlen; j++) { @@ -143,7 +157,7 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le } static int rle_unpack(const unsigned char *src, unsigned char *dest, - int src_len, int dest_len) + int src_count, int src_size, int dest_len) { const unsigned char *ps; unsigned char *pd; @@ -152,31 +166,40 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest, ps = src; pd = dest; - if (src_len & 1) + if (src_count & 1) { + if (src_size < 1) + return 0; *pd++ = *ps++; + src_size--; + } - src_len >>= 1; + src_count >>= 1; i = 0; do { + if (src_size < 1) + break; l = *ps++; + src_size--; if (l & 0x80) { l = (l & 0x7F) * 2; - if (pd + l > dest_end) + if (pd + l > dest_end || src_size < l) return ps - src; memcpy(pd, ps, l); ps += l; + src_size -= l; pd += l; } else { - if (pd + i > dest_end) + if (pd + i > dest_end || src_size < 2) return ps - src; for (i = 0; i < l; i++) { *pd++ = ps[0]; *pd++ = ps[1]; } ps += 2; + src_size -= 2; } i += l; - } while (i < src_len); + } while (i < src_count); return ps - src; } @@ -191,6 +214,7 @@ static void vmd_decode(VmdVideoContext *s) const unsigned char *p = s->buf + 16; const unsigned char *pb; + unsigned int pb_size; unsigned char meth; unsigned char *dp; /* pointer to current frame */ unsigned char *pp; /* pointer to previous frame */ @@ -204,6 +228,16 @@ static void vmd_decode(VmdVideoContext *s) frame_y = AV_RL16(&s->buf[8]); frame_width = AV_RL16(&s->buf[10]) - frame_x + 1; frame_height = AV_RL16(&s->buf[12]) - frame_y + 1; + if (frame_x < 0 || frame_width < 0 || + frame_x >= s->avctx->width || + frame_width > s->avctx->width || + frame_x + frame_width > s->avctx->width) + return; + if (frame_y < 0 || frame_height < 0 || + frame_y >= s->avctx->height || + frame_height > s->avctx->height || + frame_y + frame_height > s->avctx->height) + return; if ((frame_width == s->avctx->width && frame_height == s->avctx->height) && (frame_x || frame_y)) { @@ -216,8 +250,9 @@ static void vmd_decode(VmdVideoContext *s) /* if only a certain region will be updated, copy the entire previous * frame before the decode */ - if (frame_x || frame_y || (frame_width != s->avctx->width) || - (frame_height != s->avctx->height)) { + if (s->prev_frame.data[0] && + (frame_x || frame_y || (frame_width != s->avctx->width) || + (frame_height != s->avctx->height))) { memcpy(s->frame.data[0], s->prev_frame.data[0], s->avctx->height * s->frame.linesize[0]); @@ -235,14 +270,19 @@ static void vmd_decode(VmdVideoContext *s) } s->size -= (256 * 3 + 2); } - if (s->size >= 0) { + if (s->size > 0) { /* originally UnpackFrame in VAG's code */ pb = p; - meth = *pb++; + pb_size = s->buf + s->size - pb; + if (pb_size < 1) + return; + meth = *pb++; pb_size--; if (meth & 0x80) { - lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size); + lz_unpack(pb, pb_size, + s->unpack_buffer, s->unpack_buffer_size); meth &= 0x7F; pb = s->unpack_buffer; + pb_size = s->unpack_buffer_size; } dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x]; @@ -252,17 +292,21 @@ static void vmd_decode(VmdVideoContext *s) for (i = 0; i < frame_height; i++) { ofs = 0; do { + if (pb_size < 1) + return; len = *pb++; + pb_size--; if (len & 0x80) { len = (len & 0x7F) + 1; - if (ofs + len > frame_width) + if (ofs + len > frame_width || pb_size < len) return; memcpy(&dp[ofs], pb, len); pb += len; + pb_size -= len; ofs += len; } else { /* interframe pixel copy */ - if (ofs + len + 1 > frame_width) + if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) return; memcpy(&dp[ofs], &pp[ofs], len + 1); ofs += len + 1; @@ -280,8 +324,11 @@ static void vmd_decode(VmdVideoContext *s) case 2: for (i = 0; i < frame_height; i++) { + if (pb_size < frame_width) + return; memcpy(dp, pb, frame_width); pb += frame_width; + pb_size -= frame_width; dp += s->frame.linesize[0]; pp += s->prev_frame.linesize[0]; } @@ -291,18 +338,27 @@ static void vmd_decode(VmdVideoContext *s) for (i = 0; i < frame_height; i++) { ofs = 0; do { + if (pb_size < 1) + return; len = *pb++; + pb_size--; if (len & 0x80) { len = (len & 0x7F) + 1; + if (pb_size < 1) + return; if (*pb++ == 0xFF) - len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs); - else + len = rle_unpack(pb, &dp[ofs], len, pb_size, frame_width - ofs); + else { + if (pb_size < len) + return; memcpy(&dp[ofs], pb, len); + } pb += len; + pb_size -= 1 + len; ofs += len; } else { /* interframe pixel copy */ - if (ofs + len + 1 > frame_width) + if (ofs + len + 1 > frame_width || !s->prev_frame.data[0]) return; memcpy(&dp[ofs], &pp[ofs], len + 1); ofs += len + 1; From a31ccacb1a9b2abc0e140a812fb0ffca6f7c2591 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sat, 1 Oct 2011 00:45:05 +0200 Subject: [PATCH 02/10] Check for out of bound writes in the QDM2 decoder. Signed-off-by: Michael Niedermayer Signed-off-by: Justin Ruggles (cherry picked from commit 291d74a46d32183653db07818c7b3407fd50a288) Signed-off-by: Reinhard Tartler --- libavcodec/qdm2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 86847adc10..eeb7fa3528 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -76,6 +76,7 @@ do { \ #define SAMPLES_NEEDED_2(why) \ av_log (NULL,AV_LOG_INFO,"This file triggers some missing code. Please contact the developers.\nPosition: %s\n",why); +#define QDM2_MAX_FRAME_SIZE 512 typedef int8_t sb_int8_array[2][30][64]; @@ -168,7 +169,7 @@ typedef struct { /// I/O data const uint8_t *compressed_data; int compressed_size; - float output_buffer[1024]; + float output_buffer[QDM2_MAX_FRAME_SIZE * 2]; /// Synthesis filter MPADSPContext mpadsp; @@ -1797,6 +1798,8 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) avctx->channels = s->nb_channels = s->channels = AV_RB32(extradata); extradata += 4; + if (s->channels > MPA_MAX_CHANNELS) + return AVERROR_INVALIDDATA; avctx->sample_rate = AV_RB32(extradata); extradata += 4; @@ -1818,6 +1821,8 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) // something like max decodable tones s->group_order = av_log2(s->group_size) + 1; s->frame_size = s->group_size / 16; // 16 iterations per super block + if (s->frame_size > QDM2_MAX_FRAME_SIZE) + return AVERROR_INVALIDDATA; s->sub_sampling = s->fft_order - 7; s->frequency_range = 255 / (1 << (2 - s->sub_sampling)); From 0d93d5c4614fafea74bdac681673f5b32eb49063 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sat, 1 Oct 2011 00:45:04 +0200 Subject: [PATCH 03/10] Fix out of bound reads in the QDM2 decoder. Signed-off-by: Michael Niedermayer Signed-off-by: Justin Ruggles (cherry picked from commit 5a19acb17ceb71657b0eec51dac651953520e5c8) Signed-off-by: Reinhard Tartler --- libavcodec/qdm2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index eeb7fa3528..d1619ef131 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -1354,6 +1354,8 @@ static void qdm2_fft_decode_tones (QDM2Context *q, int duration, GetBitContext * return; local_int_14 = (offset >> local_int_8); + if (local_int_14 >= FF_ARRAY_ELEMS(fft_level_index_table)) + return; if (q->nb_channels > 1) { channel = get_bits1(gb); From 73472053516f82b7d273a3d42c583f894077a191 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 14 Sep 2011 13:57:04 -0400 Subject: [PATCH 04/10] qdm2: check output buffer size before decoding (cherry picked from commit 7d49f79f1cd47783a963a757a6563b9cac29db62) Signed-off-by: Reinhard Tartler --- libavcodec/qdm2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index d1619ef131..7e7051fc6d 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -1959,13 +1959,20 @@ static int qdm2_decode_frame(AVCodecContext *avctx, int buf_size = avpkt->size; QDM2Context *s = avctx->priv_data; int16_t *out = data; - int i; + int i, out_size; if(!buf) return 0; if(buf_size < s->checksum_size) return -1; + out_size = 16 * s->channels * s->frame_size * + av_get_bytes_per_sample(avctx->sample_fmt); + if (*data_size < out_size) { + av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n"); + return AVERROR(EINVAL); + } + av_log(avctx, AV_LOG_DEBUG, "decode(%d): %p[%d] -> %p[%d]\n", buf_size, buf, s->checksum_size, data, *data_size); @@ -1975,7 +1982,7 @@ static int qdm2_decode_frame(AVCodecContext *avctx, out += s->channels * s->frame_size; } - *data_size = (uint8_t*)out - (uint8_t*)data; + *data_size = out_size; return s->checksum_size; } From 28acce2861a07b6b78204a2cbc90bbdeed285405 Mon Sep 17 00:00:00 2001 From: Thierry Foucu Date: Fri, 18 Nov 2011 17:36:50 -0800 Subject: [PATCH 05/10] imgutils: Fix illegal read. Found with address sanitizer. Signed-off-by: Alex Converse (cherry picked from commit c693aa6f71b4f539cf9df67ba42f4b1932981687) Signed-off-by: Reinhard Tartler --- libavutil/imgutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 46853cafcb..9dc4f01078 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -117,7 +117,7 @@ int av_image_fill_pointers(uint8_t *data[4], enum PixelFormat pix_fmt, int heigh has_plane[desc->comp[i].plane] = 1; total_size = size[0]; - for (i = 1; has_plane[i] && i < 4; i++) { + for (i = 1; i < 4 && has_plane[i]; i++) { int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; data[i] = data[i-1] + size[i-1]; h = (height + (1 << s) - 1) >> s; From 7367cbec1b8cf0cbb49707fb0fdfded8ec397b0d Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Tue, 16 Aug 2011 16:46:34 -0400 Subject: [PATCH 06/10] vp6: partially propagate huffman tree building errors during coeff model parsing and fix misspelling Signed-off-by: Ronald S. Bultje (cherry picked from commit f913eeea43078b3b9052efd8d8d29e7b29b39208) Signed-off-by: Reinhard Tartler --- libavcodec/vp6.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 4f3f402c70..99e2dbfa56 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -213,8 +213,8 @@ static int vp6_huff_cmp(const void *va, const void *vb) return (a->count - b->count)*16 + (b->sym - a->sym); } -static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], - const uint8_t *map, unsigned size, VLC *vlc) +static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], + const uint8_t *map, unsigned size, VLC *vlc) { Node nodes[2*VP6_MAX_HUFF_SIZE], *tmp = &nodes[size]; int a, b, i; @@ -229,9 +229,9 @@ static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], } free_vlc(vlc); - /* then build the huffman tree accodring to probabilities */ - ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, - FF_HUFFMAN_FLAG_HNODE_FIRST); + /* then build the huffman tree according to probabilities */ + return ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp, + FF_HUFFMAN_FLAG_HNODE_FIRST); } static void vp6_parse_coeff_models(VP56Context *s) From 30c08e226156e5a36a835c008c67114f22c8da8f Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Wed, 21 Sep 2011 20:46:32 +0200 Subject: [PATCH 07/10] vp6: Check for huffman tree build errors Signed-off-by: Janne Grunau (cherry picked from commit 066fff755a5d8edc660c010ddb08474d208eeade) Signed-off-by: Reinhard Tartler --- libavcodec/vp5.c | 3 ++- libavcodec/vp56.c | 4 +++- libavcodec/vp56.h | 2 +- libavcodec/vp6.c | 20 ++++++++++++-------- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index 807309f603..d61163e64c 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -116,7 +116,7 @@ static void vp5_parse_vector_models(VP56Context *s) model->vector_pdv[comp][node] = vp56_rac_gets_nn(c, 7); } -static void vp5_parse_coeff_models(VP56Context *s) +static int vp5_parse_coeff_models(VP56Context *s) { VP56RangeCoder *c = &s->c; VP56Model *model = s->modelp; @@ -160,6 +160,7 @@ static void vp5_parse_coeff_models(VP56Context *s) for (ctx=0; ctx<6; ctx++) for (node=0; node<5; node++) model->coeff_acct[pt][ct][cg][ctx][node] = av_clip(((model->coeff_ract[pt][ct][cg][node] * vp5_ract_lc[ct][cg][node][ctx][0] + 128) >> 8) + vp5_ract_lc[ct][cg][node][ctx][1], 1, 254); + return 0; } static void vp5_parse_coeff(VP56Context *s) diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c index a181978334..a6b201478e 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -537,7 +537,8 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, s->mb_type = VP56_MB_INTER_NOVEC_PF; } - s->parse_coeff_models(s); + if (s->parse_coeff_models(s)) + goto next; memset(s->prev_dc, 0, sizeof(s->prev_dc)); s->prev_dc[1][VP56_FRAME_CURRENT] = 128; @@ -601,6 +602,7 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size, } } + next: if (p->key_frame || golden_frame) { if (s->framep[VP56_FRAME_GOLDEN]->data[0] && s->framep[VP56_FRAME_GOLDEN] != s->framep[VP56_FRAME_GOLDEN2]) diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h index 5a55f7d6a1..0c34438c8f 100644 --- a/libavcodec/vp56.h +++ b/libavcodec/vp56.h @@ -46,7 +46,7 @@ typedef void (*VP56Filter)(VP56Context *s, uint8_t *dst, uint8_t *src, typedef void (*VP56ParseCoeff)(VP56Context *s); typedef void (*VP56DefaultModelsInit)(VP56Context *s); typedef void (*VP56ParseVectorModels)(VP56Context *s); -typedef void (*VP56ParseCoeffModels)(VP56Context *s); +typedef int (*VP56ParseCoeffModels)(VP56Context *s); typedef int (*VP56ParseHeader)(VP56Context *s, const uint8_t *buf, int buf_size, int *golden_frame); diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 99e2dbfa56..3da2e2cbfa 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -234,7 +234,7 @@ static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[], FF_HUFFMAN_FLAG_HNODE_FIRST); } -static void vp6_parse_coeff_models(VP56Context *s) +static int vp6_parse_coeff_models(VP56Context *s) { VP56RangeCoder *c = &s->c; VP56Model *model = s->modelp; @@ -279,15 +279,18 @@ static void vp6_parse_coeff_models(VP56Context *s) if (s->use_huffman) { for (pt=0; pt<2; pt++) { - vp6_build_huff_tree(s, model->coeff_dccv[pt], - vp6_huff_coeff_map, 12, &s->dccv_vlc[pt]); - vp6_build_huff_tree(s, model->coeff_runv[pt], - vp6_huff_run_map, 9, &s->runv_vlc[pt]); + if (vp6_build_huff_tree(s, model->coeff_dccv[pt], + vp6_huff_coeff_map, 12, &s->dccv_vlc[pt])) + return -1; + if (vp6_build_huff_tree(s, model->coeff_runv[pt], + vp6_huff_run_map, 9, &s->runv_vlc[pt])) + return -1; for (ct=0; ct<3; ct++) for (cg = 0; cg < 6; cg++) - vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg], - vp6_huff_coeff_map, 12, - &s->ract_vlc[pt][ct][cg]); + if (vp6_build_huff_tree(s, model->coeff_ract[pt][ct][cg], + vp6_huff_coeff_map, 12, + &s->ract_vlc[pt][ct][cg])) + return -1; } memset(s->nb_null, 0, sizeof(s->nb_null)); } else { @@ -297,6 +300,7 @@ static void vp6_parse_coeff_models(VP56Context *s) for (node=0; node<5; node++) model->coeff_dcct[pt][ctx][node] = av_clip(((model->coeff_dccv[pt][node] * vp6_dccv_lc[ctx][node][0] + 128) >> 8) + vp6_dccv_lc[ctx][node][1], 1, 255); } + return 0; } static void vp6_parse_vector_adjustment(VP56Context *s, VP56mv *vect) From c76505e0dee0890e39636ddebd2707ab3ea5b8de Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Fri, 23 Sep 2011 22:36:11 +0200 Subject: [PATCH 08/10] vp6: Reset the internal state when aborting key frames header parsing It prevents leaving the state only half initialized. Signed-off-by: Janne Grunau (cherry picked from commit a72cad0a6c05aa74940101e937cb3dc602d7d67b) Signed-off-by: Reinhard Tartler --- libavcodec/vp6.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 3da2e2cbfa..48d7e7bf5b 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -137,8 +137,11 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size, if (coeff_offset) { buf += coeff_offset; buf_size -= coeff_offset; - if (buf_size < 0) + if (buf_size < 0) { + if (s->framep[VP56_FRAME_CURRENT]->key_frame) + avcodec_set_dimensions(s->avctx, 0, 0); return 0; + } if (s->use_huffman) { s->parse_coeff = vp6_parse_coeff_huffman; init_get_bits(&s->gb, buf, buf_size<<3); From 67a7ed623b678a84c992dd7bf3e3d0329f83621b Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Thu, 3 Nov 2011 15:55:52 -0700 Subject: [PATCH 09/10] vp6: Fix illegal read. (cherry picked from commit 2a6eb06254df79e96b3d791b6b89b2534ced3119) Signed-off-by: Reinhard Tartler --- libavcodec/vp6.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index 48d7e7bf5b..ecfc81f048 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -374,7 +374,7 @@ static void vp6_parse_coeff_huffman(VP56Context *s) if (b > 3) pt = 1; vlc_coeff = &s->dccv_vlc[pt]; - for (coeff_idx=0; coeff_idx<64; ) { + for (coeff_idx = 0;;) { int run = 1; if (coeff_idx<2 && s->nb_null[coeff_idx][pt]) { s->nb_null[coeff_idx][pt]--; @@ -411,6 +411,8 @@ static void vp6_parse_coeff_huffman(VP56Context *s) } } coeff_idx+=run; + if (coeff_idx >= 64) + break; cg = FFMIN(vp6_coeff_groups[coeff_idx], 3); vlc_coeff = &s->ract_vlc[pt][ct][cg]; } From ba4b08b78918f399f9c9524750b26e904d146078 Mon Sep 17 00:00:00 2001 From: Thierry Foucu Date: Thu, 17 Nov 2011 09:39:52 -0800 Subject: [PATCH 10/10] vp6: Fix illegal read. Found with Address Sanitizer Signed-off-by: Alex Converse (cherry picked from commit e0966eb140b3569b3d6b5b5008961944ef229c06) Signed-off-by: Reinhard Tartler --- libavcodec/vp6.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index ecfc81f048..02fe70bf7f 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -440,7 +440,8 @@ static void vp6_parse_coeff(VP56Context *s) model1 = model->coeff_dccv[pt]; model2 = model->coeff_dcct[pt][ctx]; - for (coeff_idx=0; coeff_idx<64; ) { + coeff_idx = 0; + for (;;) { if ((coeff_idx>1 && ct==0) || vp56_rac_get_prob(c, model2[0])) { /* parse a coeff */ if (vp56_rac_get_prob(c, model2[2])) { @@ -481,8 +482,10 @@ static void vp6_parse_coeff(VP56Context *s) run += vp56_rac_get_prob(c, model3[i+8]) << i; } } - - cg = vp6_coeff_groups[coeff_idx+=run]; + coeff_idx += run; + if (coeff_idx >= 64) + break; + cg = vp6_coeff_groups[coeff_idx]; model1 = model2 = model->coeff_ract[pt][ct][cg]; }