diff options
author | Michael Niedermayer <michael@niedermayer.cc> | 2017-02-28 03:55:02 +0100 |
---|---|---|
committer | Michael Niedermayer <michael@niedermayer.cc> | 2017-05-20 03:41:32 +0200 |
commit | b38272297247d1b2f78db0c79c24440b419aefdc (patch) | |
tree | 872206afae9aca553fc4d99c7127e380007e240c | |
parent | d19550189ff8f61b9120a458ed36bfc836c54444 (diff) | |
download | ffmpeg-b38272297247d1b2f78db0c79c24440b419aefdc.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>
(cherry picked from commit 7b5ff7d57355dc608f0fd86e3ab32a2fda65e752)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
-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 cb0c7cdc02..742e73d12e 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -2274,7 +2274,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; @@ -2290,6 +2290,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 @@ -2393,18 +2397,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, @@ -2487,13 +2492,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 2135bd9d83..6be0a55368 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -282,7 +282,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; |