From: Michael Niedermayer Date: Fri, 23 Mar 2012 23:20:05 +0000 (+0100) Subject: pthread/mpegvideo: detect and block attempts to init frames after setup. X-Git-Tag: android-x86-4.4-r1~12811 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=59a4b73531428d2f420b4dad545172c8483ced0f;p=android-x86%2Fexternal-ffmpeg.git pthread/mpegvideo: detect and block attempts to init frames after setup. This fixes race conditions that ultimately lead to memory corruption. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind Signed-off-by: Michael Niedermayer --- diff --git a/libavcodec/internal.h b/libavcodec/internal.h index fb2c0dbe56..dfef6eb31f 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -157,4 +157,6 @@ static av_always_inline int64_t ff_samples_to_time_base(AVCodecContext *avctx, avctx->time_base); } +int ff_thread_can_start_frame(AVCodecContext *avctx); + #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 62670a6f5e..017bbdfba1 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -1134,6 +1134,11 @@ int ff_MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) assert(s->last_picture_ptr == NULL || s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3); + if (!ff_thread_can_start_frame(avctx)) { + av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + /* mark & release old frames */ if (s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3) { if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c index 7834922f9f..d8f8858c1e 100644 --- a/libavcodec/pthread.c +++ b/libavcodec/pthread.c @@ -932,6 +932,17 @@ static int *allocate_progress(PerThreadContext *p) return p->progress[i]; } +int ff_thread_can_start_frame(AVCodecContext *avctx) +{ + PerThreadContext *p = avctx->thread_opaque; + if ((avctx->active_thread_type&FF_THREAD_FRAME) && p->state != STATE_SETTING_UP && + (avctx->codec->update_thread_context || (!avctx->thread_safe_callbacks && + avctx->get_buffer != avcodec_default_get_buffer))) { + return 0; + } + return 1; +} + int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f) { PerThreadContext *p = avctx->thread_opaque; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index e918024ca5..58435d43aa 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -2285,6 +2285,11 @@ void ff_thread_await_progress(AVFrame *f, int progress, int field) { } +int ff_thread_can_start_frame(AVCodecContext *avctx) +{ + return 1; +} + #endif enum AVMediaType avcodec_get_type(enum CodecID codec_id)