From 7aa2c320924b41edd5ba8be5dfdcb521f7f42a48 Mon Sep 17 00:00:00 2001
From: "Ronald S. Bultje" <rsbultje@gmail.com>
Date: Thu, 20 Oct 2011 17:25:53 -0700
Subject: [PATCH] vp3: fix double free and invalid read.

If token < 0, we read invalid memory. Also, if the last decoding
iteration before codec close had an error, we didn't sync the frame
list and may end up free()'ing e.g. what was "last" for one thread
and "current" for another thread, i.e. double free(). Thus, on error,
simply erase the framelist.
---
 libavcodec/vp3.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index 9262c27..62acabf 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -890,7 +890,7 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
             /* decode a VLC into a token */
             token = get_vlc2(gb, vlc_table, 11, 3);
             /* use the token to get a zero run, a coefficient, and an eob run */
-            if (token <= 6) {
+            if ((unsigned) token <= 6U) {
                 eob_run = eob_run_base[token];
                 if (eob_run_get_bits[token])
                     eob_run += get_bits(gb, eob_run_get_bits[token]);
@@ -908,7 +908,7 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
                     coeff_i        += eob_run;
                     eob_run = 0;
                 }
-            } else {
+            } else if (token >= 0) {
                 bits_to_get = coeff_get_bits[token];
                 if (bits_to_get)
                     bits_to_get = get_bits(gb, bits_to_get);
@@ -1777,10 +1777,15 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *
     Vp3DecodeContext *s = dst->priv_data, *s1 = src->priv_data;
     int qps_changed = 0, i, err;
 
+#define copy_fields(to, from, start_field, end_field) memcpy(&to->start_field, &from->start_field, (char*)&to->end_field - (char*)&to->start_field)
+
     if (!s1->current_frame.data[0]
         ||s->width != s1->width
-        ||s->height!= s1->height)
+        ||s->height!= s1->height) {
+        if (s != s1)
+            copy_fields(s, s1, golden_frame, current_frame);
         return -1;
+    }
 
     if (s != s1) {
         // init tables if the first frame hasn't been decoded
@@ -1796,8 +1801,6 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext *
             memcpy(s->motion_val[1], s1->motion_val[1], c_fragment_count * sizeof(*s->motion_val[1]));
         }
 
-#define copy_fields(to, from, start_field, end_field) memcpy(&to->start_field, &from->start_field, (char*)&to->end_field - (char*)&to->start_field)
-
         // copy previous frame data
         copy_fields(s, s1, golden_frame, dsp);
 
-- 
1.7.6

