[FFmpeg-cvslog] pthread/mpegvideo: detect and block attempts to init frames after setup.
Michael Niedermayer
git at videolan.org
Sat Mar 24 00:37:43 CET 2012
ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Sat Mar 24 00:20:05 2012 +0100| [59a4b73531428d2f420b4dad545172c8483ced0f] | committer: Michael Niedermayer
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 <michaelni at gmx.at>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=59a4b73531428d2f420b4dad545172c8483ced0f
---
libavcodec/internal.h | 2 ++
libavcodec/mpegvideo.c | 5 +++++
libavcodec/pthread.c | 11 +++++++++++
libavcodec/utils.c | 5 +++++
4 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index fb2c0db..dfef6eb 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 62670a6..017bbdf 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 7834922..d8f8858 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 e918024..58435d4 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)
More information about the ffmpeg-cvslog
mailing list