mimic: don't use self as reference, and report completion at end of decode( ).

Message ID 20120316223431.138F35E0D9@aruru.libav.org
State New
Headers show

Commit Message

Janne Grunau March 16, 2012, 10:34 p.m.
Module: libav
Branch: master
Commit: 80387f0e2568746dce4a68e2217297029a053dae

Author:    Ronald S. Bultje <rsbultje@gmail.com>
Committer: Ronald S. Bultje <rsbultje@gmail.com>
Date:      Fri Mar 16 14:04:00 2012 -0700

mimic: don't use self as reference, and report completion at end of decode().

Fixes hangs on corrupt samples that reference self-frames.

Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
CC: libav-stable@libav.org

---

 libavcodec/mimic.c |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

Patch

diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c
index aa14f64..33c5f7b 100644
--- a/libavcodec/mimic.c
+++ b/libavcodec/mimic.c
@@ -259,8 +259,8 @@  static int decode(MimicContext *ctx, int quality, int num_coeffs,
                         int index = (ctx->cur_index+backref)&15;
                         uint8_t *p = ctx->flipped_ptrs[index].data[0];
 
-                        ff_thread_await_progress(&ctx->buf_ptrs[index], cur_row, 0);
-                        if(p) {
+                        if (index != ctx->cur_index && p) {
+                            ff_thread_await_progress(&ctx->buf_ptrs[index], cur_row, 0);
                             p += src -
                                 ctx->flipped_ptrs[ctx->prev_index].data[plane];
                             ctx->dsp.put_pixels_tab[1][0](dst, p, stride, 8);
@@ -311,6 +311,7 @@  static int mimic_decode_frame(AVCodecContext *avctx, void *data,
     int width, height;
     int quality, num_coeffs;
     int swap_buf_size = buf_size - MIMIC_HEADER_SIZE;
+    int res;
 
     if (buf_size <= MIMIC_HEADER_SIZE) {
         av_log(avctx, AV_LOG_ERROR, "insufficient data\n");
@@ -379,10 +380,10 @@  static int mimic_decode_frame(AVCodecContext *avctx, void *data,
                         swap_buf_size>>2);
     init_get_bits(&ctx->gb, ctx->swap_buf, swap_buf_size << 3);
 
-    if(!decode(ctx, quality, num_coeffs, !is_pframe)) {
-        if (avctx->active_thread_type&FF_THREAD_FRAME)
-            ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], INT_MAX, 0);
-        else {
+    res = decode(ctx, quality, num_coeffs, !is_pframe);
+    ff_thread_report_progress(&ctx->buf_ptrs[ctx->cur_index], INT_MAX, 0);
+    if (!res) {
+        if (!(avctx->active_thread_type & FF_THREAD_FRAME)) {
             ff_thread_release_buffer(avctx, &ctx->buf_ptrs[ctx->cur_index]);
             return -1;
         }