[FFmpeg-cvslog] avcodec/h264: Fix race between slices where one overwrites data from the next
Michael Niedermayer
git at videolan.org
Tue Apr 7 13:07:35 CEST 2015
ffmpeg | branch: release/2.2 | Michael Niedermayer <michaelni at gmx.at> | Tue Apr 7 00:40:21 2015 +0200| [3852b172e7de8fee4b78ff3f5026a9a13c7329d5] | committer: Michael Niedermayer
avcodec/h264: Fix race between slices where one overwrites data from the next
Fixes non deterministic crash in ticket4408/fuzz2.264
Likely fixes other samples as well
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
(cherry picked from commit 43b434210e597d484aef57c4139c3126d22b7e2b)
Conflicts:
libavcodec/h264.h
libavcodec/h264_slice.c
(cherry picked from commit dbbc42858e87cdd04e6c3b7694f8b394d4bfcdc6)
Conflicts:
libavcodec/h264_slice.c
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=3852b172e7de8fee4b78ff3f5026a9a13c7329d5
---
libavcodec/h264.c | 43 ++++++++++++++++++++++++++++++++++++++-----
libavcodec/h264.h | 1 +
2 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 155877b..30b20c9 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -4635,8 +4635,17 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
for (;;) {
// START_TIMER
- int ret = ff_h264_decode_mb_cabac(h);
- int eos;
+ int ret, eos;
+
+ if (h->mb_x + h->mb_y * h->mb_width >= h->mb_index_end) {
+ av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps next at %d\n",
+ h->mb_index_end);
+ er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x,
+ h->mb_y, ER_MB_ERROR);
+ return AVERROR_INVALIDDATA;
+ }
+
+ ret = ff_h264_decode_mb_cabac(h);
// STOP_TIMER("decode_mb_cabac")
if (ret >= 0)
@@ -4698,7 +4707,17 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg)
}
} else {
for (;;) {
- int ret = ff_h264_decode_mb_cavlc(h);
+ int ret;
+
+ if (h->mb_x + h->mb_y * h->mb_width >= h->mb_index_end) {
+ av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps next at %d\n",
+ h->mb_index_end);
+ er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x,
+ h->mb_y, ER_MB_ERROR);
+ return AVERROR_INVALIDDATA;
+ }
+
+ ret = ff_h264_decode_mb_cavlc(h);
if (ret >= 0)
ff_h264_hl_decode_mb(h);
@@ -4789,19 +4808,33 @@ static int execute_decode_slices(H264Context *h, unsigned context_count)
av_assert0(h->mb_y < h->mb_height);
+ h->mb_index_end = INT_MAX;
+
if (h->avctx->hwaccel ||
h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
return 0;
if (context_count == 1) {
return decode_slice(avctx, &h);
} else {
+ int j, mb_index;
av_assert0(context_count > 0);
- for (i = 1; i < context_count; i++) {
+ for (i = 0; i < context_count; i++) {
+ int mb_index_end = h->mb_width * h->mb_height;
hx = h->thread_context[i];
- if (CONFIG_ERROR_RESILIENCE) {
+ mb_index = hx->resync_mb_x + hx->resync_mb_y * h->mb_width;
+ if (CONFIG_ERROR_RESILIENCE && i) {
hx->er.error_count = 0;
}
hx->x264_build = h->x264_build;
+ for (j = 0; j < context_count; j++) {
+ H264Context *sl2 = h->thread_context[j];
+ int mb_index2 = sl2->resync_mb_x + sl2->resync_mb_y * h->mb_width;
+
+ if (i==j || mb_index > mb_index2)
+ continue;
+ mb_index_end = FFMIN(mb_index_end, mb_index2);
+ }
+ hx->mb_index_end = mb_index_end;
}
avctx->execute(avctx, decode_slice, h->thread_context,
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 66c1473..6a3e570 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -488,6 +488,7 @@ typedef struct H264Context {
int mb_x, mb_y;
int resync_mb_x;
int resync_mb_y;
+ int mb_index_end;
int mb_skip_run;
int mb_height, mb_width;
int mb_stride;
More information about the ffmpeg-cvslog
mailing list