diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2017-02-28 03:55:02 +0100 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2017-03-01 14:07:33 +0100 |
commit | 7b5ff7d57355dc608f0fd86e3ab32a2fda65e752 (patch) | |
tree | a137fd528071d3c8e1cbfefbfa55932bcdbf2633 /libavcodec | |
parent | 4bd3f1ce3e68a9348e97ec07a247048ea72ed808 (diff) | |
download | ffmpeg-7b5ff7d57355dc608f0fd86e3ab32a2fda65e752.tar.gz |
avcodec/vp8: Check for bitsteam end in decode_mb_row_no_filter()
Fixes timeout with 686/clusterfuzz-testcase-5853946876788736
this shortcuts (i.e. speeds up) the error and
return-to-user when decoding a truncated frame
Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/targets/ffmpeg
Previous version reviewed by: "Ronald S. Bultje" <rsbultje@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/vp8.c | 20 | ||||
-rw-r--r-- | libavcodec/vp8.h | 2 |
2 files changed, 15 insertions, 7 deletions
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index c1c3eb7072..cc158528ef 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -2275,7 +2275,7 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame, #define update_pos(td, mb_y, mb_x) while(0) #endif -static av_always_inline void decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, +static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr, int is_vp7) { VP8Context *s = avctx->priv_data; @@ -2291,6 +2291,10 @@ static av_always_inline void decode_mb_row_no_filter(AVCodecContext *avctx, void curframe->tf.f->data[1] + 8 * mb_y * s->uvlinesize, curframe->tf.f->data[2] + 8 * mb_y * s->uvlinesize }; + + if (c->end <= c->buffer && c->bits >= 0) + return AVERROR_INVALIDDATA; + if (mb_y == 0) prev_td = td; else @@ -2394,18 +2398,19 @@ static av_always_inline void decode_mb_row_no_filter(AVCodecContext *avctx, void update_pos(td, mb_y, mb_x); } } + return 0; } -static void vp7_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, +static int vp7_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr) { - decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 1); + return decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 1); } -static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, +static int vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr) { - decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 0); + return decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 0); } static av_always_inline void filter_mb_row(AVCodecContext *avctx, void *tdata, @@ -2488,13 +2493,16 @@ int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr, VP8ThreadData *next_td = NULL, *prev_td = NULL; VP8Frame *curframe = s->curframe; int mb_y, num_jobs = s->num_jobs; + int ret; td->thread_nr = threadnr; for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) { if (mb_y >= s->mb_height) break; td->thread_mb_pos = mb_y << 16; - s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr); + ret = s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr); + if (ret < 0) + return ret; if (s->deblock_filter) s->filter_mb_row(avctx, tdata, jobnr, threadnr); update_pos(td, mb_y, INT_MAX & 0xFFFF); diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h index 374e1388e2..6218fe0567 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -275,7 +275,7 @@ typedef struct VP8Context { */ int mb_layout; - void (*decode_mb_row_no_filter)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr); + int (*decode_mb_row_no_filter)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr); void (*filter_mb_row)(AVCodecContext *avctx, void *tdata, int jobnr, int threadnr); int vp7; |