From 05e0061ef6494ced1f74881d4fa3d4a0dd6ddb69 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 14 Mar 2012 03:47:52 +0000 Subject: fate: add pam image regression test Signed-off-by: Paul B Mahol Signed-off-by: Janne Grunau --- tests/lavf-regression.sh | 4 ++++ tests/ref/lavf/pam | 3 +++ 2 files changed, 7 insertions(+) create mode 100644 tests/ref/lavf/pam diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh index 49d2dfc9cd..c779bbd887 100755 --- a/tests/lavf-regression.sh +++ b/tests/lavf-regression.sh @@ -171,6 +171,10 @@ if [ -n "$do_jpg" ] ; then do_image_formats jpg "-pix_fmt yuvj420p" "-f image2" fi +if [ -n "$do_pam" ] ; then +do_image_formats pam +fi + if [ -n "$do_pcx" ] ; then do_image_formats pcx fi diff --git a/tests/ref/lavf/pam b/tests/ref/lavf/pam new file mode 100644 index 0000000000..972d72825e --- /dev/null +++ b/tests/ref/lavf/pam @@ -0,0 +1,3 @@ +0dce5565222cf0f8b309467f279aecd2 *./tests/data/images/pam/02.pam +./tests/data/images/pam/%02d.pam CRC=0x6da01946 + 304191 ./tests/data/images/pam/02.pam -- cgit v1.2.3 From d3d1b25e6991aaa171c1a4082164e15e6e5b1b83 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 14 Mar 2012 03:14:01 +0000 Subject: jv demux: set video stream duration Signed-off-by: Paul B Mahol Signed-off-by: Janne Grunau --- libavformat/jvdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/jvdec.c b/libavformat/jvdec.c index c42e302bda..567f4625e0 100644 --- a/libavformat/jvdec.c +++ b/libavformat/jvdec.c @@ -79,6 +79,7 @@ static int read_header(AVFormatContext *s) vst->codec->codec_tag = 0; /* no fourcc */ vst->codec->width = avio_rl16(pb); vst->codec->height = avio_rl16(pb); + vst->duration = vst->nb_frames = ast->nb_index_entries = avio_rl16(pb); avpriv_set_pts_info(vst, 64, avio_rl16(pb), 1000); -- cgit v1.2.3 From a1c036e961a32f7208e7315dabfa0ee99d779edb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 14 Mar 2012 03:02:02 +0000 Subject: jvdec: unbreak video decoding The safe bitstream reader broke it since the buffer size was specified in bytes instead of bits. Signed-off-by: Janne Grunau CC: libav-stable@libav.org --- libavcodec/jvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index 5d4fdea009..ffa2f5a558 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -150,7 +150,7 @@ static int decode_frame(AVCodecContext *avctx, if (video_type == 0 || video_type == 1) { GetBitContext gb; - init_get_bits(&gb, buf, FFMIN(video_size, (buf_end - buf) * 8)); + init_get_bits(&gb, buf, 8 * FFMIN(video_size, buf_end - buf)); for (j = 0; j < avctx->height; j += 8) for (i = 0; i < avctx->width; i += 8) -- cgit v1.2.3 From f1ce053cd0e0d7dc67fa61f32bcd8b6ee5e5c490 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 13 Mar 2012 14:14:59 +0000 Subject: bytestream: add more unchecked variants for bytestream2 API Signed-off-by: Paul B Mahol Signed-off-by: Ronald S. Bultje --- libavcodec/bytestream.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libavcodec/bytestream.h b/libavcodec/bytestream.h index 4d686e550a..68146200ae 100644 --- a/libavcodec/bytestream.h +++ b/libavcodec/bytestream.h @@ -170,6 +170,12 @@ static av_always_inline void bytestream2_skip(GetByteContext *g, g->buffer += FFMIN(g->buffer_end - g->buffer, size); } +static av_always_inline void bytestream2_skipu(GetByteContext *g, + unsigned int size) +{ + g->buffer += size; +} + static av_always_inline void bytestream2_skip_p(PutByteContext *p, unsigned int size) { @@ -257,6 +263,15 @@ static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, return size2; } +static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, + uint8_t *dst, + unsigned int size) +{ + memcpy(dst, g->buffer, size); + g->buffer += size; + return size; +} + static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, const uint8_t *src, unsigned int size) @@ -272,6 +287,15 @@ static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p, return size2; } +static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p, + const uint8_t *src, + unsigned int size) +{ + memcpy(p->buffer, src, size); + p->buffer += size; + return size; +} + static av_always_inline void bytestream2_set_buffer(PutByteContext *p, const uint8_t c, unsigned int size) @@ -286,6 +310,14 @@ static av_always_inline void bytestream2_set_buffer(PutByteContext *p, p->buffer += size2; } +static av_always_inline void bytestream2_set_bufferu(PutByteContext *p, + const uint8_t c, + unsigned int size) +{ + memset(p->buffer, c, size); + p->buffer += size; +} + static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p) { return p->eof; -- cgit v1.2.3 From 5b4d026a030a775f0bd287e3a27188e8b5c9009f Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 13 Mar 2012 18:13:38 +0000 Subject: anm: convert to bytestream2 API Protects from overreads. Signed-off-by: Paul B Mahol Signed-off-by: Ronald S. Bultje --- libavcodec/anm.c | 60 +++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/libavcodec/anm.c b/libavcodec/anm.c index 46002f80fc..c2d22cb366 100644 --- a/libavcodec/anm.c +++ b/libavcodec/anm.c @@ -30,25 +30,25 @@ typedef struct AnmContext { AVFrame frame; int palette[AVPALETTE_COUNT]; + GetByteContext gb; int x; ///< x coordinate position } AnmContext; static av_cold int decode_init(AVCodecContext *avctx) { AnmContext *s = avctx->priv_data; - const uint8_t *buf; int i; avctx->pix_fmt = PIX_FMT_PAL8; - if (avctx->extradata_size != 16*8 + 4*256) - return -1; - s->frame.reference = 1; + bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size); + if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256) + return -1; - buf = avctx->extradata + 16*8; + bytestream2_skipu(&s->gb, 16 * 8); for (i = 0; i < 256; i++) - s->palette[i] = bytestream_get_le32(&buf); + s->palette[i] = bytestream2_get_le32u(&s->gb); return 0; } @@ -56,7 +56,7 @@ static av_cold int decode_init(AVCodecContext *avctx) /** * Perform decode operation * @param dst, dst_end Destination image buffer - * @param buf, buf_end Source buffer (optional, see below) + * @param gb, GetByteContext (optional, see below) * @param pixel Fill color (optional, see below) * @param count Pixel count * @param x Pointer to x-axis counter @@ -64,24 +64,22 @@ static av_cold int decode_init(AVCodecContext *avctx) * @param linesize Destination image buffer linesize * @return non-zero if destination buffer is exhausted * - * a copy operation is achieved when 'buf' is set - * a fill operation is acheived when 'buf' is null and pixel is >= 0 - * a skip operation is acheived when 'buf' is null and pixel is < 0 + * a copy operation is achieved when 'gb' is set + * a fill operation is acheived when 'gb' is null and pixel is >= 0 + * a skip operation is acheived when 'gb' is null and pixel is < 0 */ static inline int op(uint8_t **dst, const uint8_t *dst_end, - const uint8_t **buf, const uint8_t *buf_end, + GetByteContext *gb, int pixel, int count, int *x, int width, int linesize) { int remaining = width - *x; while(count > 0) { int striplen = FFMIN(count, remaining); - if (buf) { - striplen = FFMIN(striplen, buf_end - *buf); - if (*buf >= buf_end) + if (gb) { + if (bytestream2_get_bytes_left(gb) < striplen) goto exhausted; - memcpy(*dst, *buf, striplen); - *buf += striplen; + bytestream2_get_bufferu(gb, *dst, striplen); } else if (pixel >= 0) memset(*dst, pixel, striplen); *dst += striplen; @@ -110,9 +108,7 @@ static int decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { AnmContext *s = avctx->priv_data; - const uint8_t *buf = avpkt->data; const int buf_size = avpkt->size; - const uint8_t *buf_end = buf + buf_size; uint8_t *dst, *dst_end; int count; @@ -123,35 +119,37 @@ static int decode_frame(AVCodecContext *avctx, dst = s->frame.data[0]; dst_end = s->frame.data[0] + s->frame.linesize[0]*avctx->height; - if (buf[0] != 0x42) { + bytestream2_init(&s->gb, avpkt->data, buf_size); + + if (bytestream2_get_byte(&s->gb) != 0x42) { av_log_ask_for_sample(avctx, "unknown record type\n"); return buf_size; } - if (buf[1]) { + if (bytestream2_get_byte(&s->gb)) { av_log_ask_for_sample(avctx, "padding bytes not supported\n"); return buf_size; } - buf += 4; + bytestream2_skip(&s->gb, 2); s->x = 0; do { /* if statements are ordered by probability */ -#define OP(buf, pixel, count) \ - op(&dst, dst_end, (buf), buf_end, (pixel), (count), &s->x, avctx->width, s->frame.linesize[0]) +#define OP(gb, pixel, count) \ + op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame.linesize[0]) - int type = bytestream_get_byte(&buf); + int type = bytestream2_get_byte(&s->gb); count = type & 0x7F; type >>= 7; if (count) { - if (OP(type ? NULL : &buf, -1, count)) break; + if (OP(type ? NULL : &s->gb, -1, count)) break; } else if (!type) { int pixel; - count = bytestream_get_byte(&buf); /* count==0 gives nop */ - pixel = bytestream_get_byte(&buf); + count = bytestream2_get_byte(&s->gb); /* count==0 gives nop */ + pixel = bytestream2_get_byte(&s->gb); if (OP(NULL, pixel, count)) break; } else { int pixel; - type = bytestream_get_le16(&buf); + type = bytestream2_get_le16(&s->gb); count = type & 0x3FFF; type >>= 14; if (!count) { @@ -163,11 +161,11 @@ static int decode_frame(AVCodecContext *avctx, } continue; } - pixel = type == 3 ? bytestream_get_byte(&buf) : -1; + pixel = type == 3 ? bytestream2_get_byte(&s->gb) : -1; if (type == 1) count += 0x4000; - if (OP(type == 2 ? &buf : NULL, pixel, count)) break; + if (OP(type == 2 ? &s->gb : NULL, pixel, count)) break; } - } while (buf + 1 < buf_end); + } while (bytestream2_get_bytes_left(&s->gb) > 0); memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); -- cgit v1.2.3 From 92a02d935bb73b3d5e5dcae990ffdafc7262bbd6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 14 Mar 2012 20:15:34 +0000 Subject: Add ffvhuff encoding and decoding regression test Signed-off-by: Paul B Mahol Signed-off-by: Ronald S. Bultje --- tests/codec-regression.sh | 5 +++++ tests/ref/vsynth1/ffvhuff | 4 ++++ tests/ref/vsynth2/ffvhuff | 4 ++++ 3 files changed, 13 insertions(+) create mode 100644 tests/ref/vsynth1/ffvhuff create mode 100644 tests/ref/vsynth2/ffvhuff diff --git a/tests/codec-regression.sh b/tests/codec-regression.sh index 6a1dee6e2d..cef3d443a2 100755 --- a/tests/codec-regression.sh +++ b/tests/codec-regression.sh @@ -207,6 +207,11 @@ do_video_encoding ffv1.avi "-strict -2 -an -vcodec ffv1" do_video_decoding fi +if [ -n "$do_ffvhuff" ] ; then +do_video_encoding ffvhuff.avi "-an -vcodec ffvhuff" +do_video_decoding "" +fi + if [ -n "$do_snow" ] ; then do_video_encoding snow.avi "-strict -2 -an -vcodec snow -qscale 2 -flags +qpel -me_method iter -dia_size 2 -cmp 12 -subcmp 12 -s 128x64" do_video_decoding "" "-s 352x288" diff --git a/tests/ref/vsynth1/ffvhuff b/tests/ref/vsynth1/ffvhuff new file mode 100644 index 0000000000..4a1ebdb1a3 --- /dev/null +++ b/tests/ref/vsynth1/ffvhuff @@ -0,0 +1,4 @@ +da0c0bd12ac141c976ffa6a71832ab4b *./tests/data/vsynth1/ffvhuff.avi + 5987208 ./tests/data/vsynth1/ffvhuff.avi +c5ccac874dbf808e9088bc3107860042 *./tests/data/ffvhuff.vsynth1.out.yuv +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth2/ffvhuff b/tests/ref/vsynth2/ffvhuff new file mode 100644 index 0000000000..47fc6597d7 --- /dev/null +++ b/tests/ref/vsynth2/ffvhuff @@ -0,0 +1,4 @@ +d31aab445b24f738df45fdd7479d6dd7 *./tests/data/vsynth2/ffvhuff.avi + 4988056 ./tests/data/vsynth2/ffvhuff.avi +dde5895817ad9d219f79a52d0bdfb001 *./tests/data/ffvhuff.vsynth2.out.yuv +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 -- cgit v1.2.3 From c9837954e7b968d44f82e7cdb7618e9f523b196c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 10 Mar 2012 00:08:32 +0100 Subject: snow: reject unsupported chroma shifts. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Ronald S. Bultje --- libavcodec/snowdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index 1dccc638d8..58a80b39c6 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -327,6 +327,11 @@ static int decode_header(SnowContext *s){ return -1; } + if (s->chroma_h_shift != 1 || s->chroma_v_shift != 1) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid chroma shift\n"); + return AVERROR_PATCHWELCOME; + } + s->qlog += get_symbol(&s->c, s->header_state, 1); s->mv_scale += get_symbol(&s->c, s->header_state, 1); s->qbias += get_symbol(&s->c, s->header_state, 1); -- cgit v1.2.3 From 1f8ff2b13cbfef790385818664ed12e763e7c75b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 2 Mar 2012 20:53:00 +0100 Subject: snow: check reference frame indices. Fixes NULL ptr dereference Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org Signed-off-by: Ronald S. Bultje --- libavcodec/snowdec.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index 58a80b39c6..488a953acf 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -132,7 +132,7 @@ static inline void decode_subband_slice_buffered(SnowContext *s, SubBand *b, sli return; } -static void decode_q_branch(SnowContext *s, int level, int x, int y){ +static int decode_q_branch(SnowContext *s, int level, int x, int y){ const int w= s->b_width << s->block_max_depth; const int rem_depth= s->block_max_depth - level; const int index= (x + y*w) << rem_depth; @@ -142,10 +142,11 @@ static void decode_q_branch(SnowContext *s, int level, int x, int y){ const BlockNode *tl = y && x ? &s->block[index-w-1] : left; const BlockNode *tr = y && trxblock[index-w+(1<level + 2*top->level + tl->level + tr->level; + int res; if(s->keyframe){ set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA); - return; + return 0; } if(level==s->block_max_depth || get_rac(&s->c, &s->block_state[4 + s_context])){ @@ -168,17 +169,23 @@ static void decode_q_branch(SnowContext *s, int level, int x, int y){ }else{ if(s->ref_frames > 1) ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0); + if (ref >= s->ref_frames) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid ref\n"); + return AVERROR_INVALIDDATA; + } pred_mv(s, &mx, &my, ref, left, top, tr); mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1); my+= get_symbol(&s->c, &s->block_state[128 + 32*(my_context + 16*!!ref)], 1); } set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type); }else{ - decode_q_branch(s, level+1, 2*x+0, 2*y+0); - decode_q_branch(s, level+1, 2*x+1, 2*y+0); - decode_q_branch(s, level+1, 2*x+0, 2*y+1); - decode_q_branch(s, level+1, 2*x+1, 2*y+1); + if ((res = decode_q_branch(s, level+1, 2*x+0, 2*y+0)) < 0 || + (res = decode_q_branch(s, level+1, 2*x+1, 2*y+0)) < 0 || + (res = decode_q_branch(s, level+1, 2*x+0, 2*y+1)) < 0 || + (res = decode_q_branch(s, level+1, 2*x+1, 2*y+1)) < 0) + return res; } + return 0; } static void dequantize_slice_buffered(SnowContext *s, slice_buffer * sb, SubBand *b, IDWTELEM *src, int stride, int start_y, int end_y){ @@ -354,16 +361,19 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static void decode_blocks(SnowContext *s){ +static int decode_blocks(SnowContext *s){ int x, y; int w= s->b_width; int h= s->b_height; + int res; for(y=0; ydebug&FF_DEBUG_PICT_INFO) av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog); - decode_blocks(s); + if ((res = decode_blocks(s)) < 0) + return res; for(plane_index=0; plane_index<3; plane_index++){ Plane *p= &s->plane[plane_index]; -- cgit v1.2.3 From 86020073dbb9a3a9d1fbb76345b2ca29ba1f13d2 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 13 Mar 2012 12:28:35 -0700 Subject: xa_adpcm: limit filter to prevent xa_adpcm_table[] array bounds overruns. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/adpcm.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 302f2ffe57..54c3e6d194 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -265,8 +265,9 @@ static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned c return c->predictor; } -static void xa_decode(short *out, const unsigned char *in, - ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc) +static int xa_decode(AVCodecContext *avctx, + short *out, const unsigned char *in, + ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc) { int i, j; int shift,filter,f0,f1; @@ -277,6 +278,12 @@ static void xa_decode(short *out, const unsigned char *in, shift = 12 - (in[4+i*2] & 15); filter = in[4+i*2] >> 4; + if (filter > 4) { + av_log(avctx, AV_LOG_ERROR, + "Invalid XA-ADPCM filter %d (max. allowed is 4)\n", + filter); + return AVERROR_INVALIDDATA; + } f0 = xa_adpcm_table[filter][0]; f1 = xa_adpcm_table[filter][1]; @@ -304,7 +311,12 @@ static void xa_decode(short *out, const unsigned char *in, shift = 12 - (in[5+i*2] & 15); filter = in[5+i*2] >> 4; - + if (filter > 4) { + av_log(avctx, AV_LOG_ERROR, + "Invalid XA-ADPCM filter %d (max. allowed is 4)\n", + filter); + return AVERROR_INVALIDDATA; + } f0 = xa_adpcm_table[filter][0]; f1 = xa_adpcm_table[filter][1]; @@ -328,6 +340,8 @@ static void xa_decode(short *out, const unsigned char *in, left->sample2 = s_2; } } + + return 0; } /** @@ -812,8 +826,9 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, break; case CODEC_ID_ADPCM_XA: while (buf_size >= 128) { - xa_decode(samples, src, &c->status[0], &c->status[1], - avctx->channels); + if ((ret = xa_decode(avctx, samples, src, &c->status[0], + &c->status[1], avctx->channels)) < 0) + return ret; src += 128; samples += 28 * 8; buf_size -= 128; -- cgit v1.2.3 From 48cbe4b092113eae0b3e5d6a08b59027f913a884 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 13 Mar 2012 15:21:07 -0700 Subject: h264: increase reference poc list from 16 to 32. Interlaced images can have 32 references (16 per field), so limiting the array size to 16 leads to invalid writes. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/mpegvideo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 9d9d8707c9..8f788a7c06 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -126,7 +126,7 @@ typedef struct Picture{ int pic_id; /**< h264 pic_num (short -> no wrap version of pic_num, pic_num & max_pic_num; long -> long_pic_num) */ int long_ref; ///< 1->long term reference 0->short term reference - int ref_poc[2][2][16]; ///< h264 POCs of the frames used as reference (FIXME need per slice) + int ref_poc[2][2][32]; ///< h264 POCs of the frames used as reference (FIXME need per slice) int ref_count[2][2]; ///< number of entries in ref_poc (FIXME need per slice) int mbaff; ///< h264 1 -> MBAFF frame 0-> not MBAFF int field_picture; ///< whether or not the picture was encoded in separate fields -- cgit v1.2.3 From e0febda22d0e0fab094a9c886b0e0f0f662df1ef Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 13 Mar 2012 16:26:44 -0700 Subject: h264: stricter reference limit enforcement. Progressive images can have only 16 references, error out if there are more, since the data is almost certainly corrupt, and the invalid value will lead to random crashes or invalid writes later on. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/h264.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index c3ef3f0110..64f676c4a9 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -3021,6 +3021,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ h->ref_count[1]= h->pps.ref_count[1]; if(h->slice_type_nos != AV_PICTURE_TYPE_I){ + int max_refs = s->picture_structure == PICT_FRAME ? 16 : 32; + if(h->slice_type_nos == AV_PICTURE_TYPE_B){ h->direct_spatial_mv_pred= get_bits1(&s->gb); } @@ -3030,13 +3032,14 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ h->ref_count[0]= get_ue_golomb(&s->gb) + 1; if(h->slice_type_nos==AV_PICTURE_TYPE_B) h->ref_count[1]= get_ue_golomb(&s->gb) + 1; + } - if(h->ref_count[0]-1 > 32-1 || h->ref_count[1]-1 > 32-1){ - av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow\n"); - h->ref_count[0]= h->ref_count[1]= 1; - return -1; - } + if (h->ref_count[0] > max_refs || h->ref_count[1] > max_refs) { + av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow\n"); + h->ref_count[0] = h->ref_count[1] = 1; + return AVERROR_INVALIDDATA; } + if(h->slice_type_nos == AV_PICTURE_TYPE_B) h->list_count= 2; else -- cgit v1.2.3