aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Niedermayer <michael@niedermayer.cc>2017-02-28 03:55:02 +0100
committerMichael Niedermayer <michael@niedermayer.cc>2017-05-20 03:41:32 +0200
commitb38272297247d1b2f78db0c79c24440b419aefdc (patch)
tree872206afae9aca553fc4d99c7127e380007e240c
parentd19550189ff8f61b9120a458ed36bfc836c54444 (diff)
downloadffmpeg-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.c20
-rw-r--r--libavcodec/vp8.h2
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;