]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/vp3.c
lavc: implement an ATRAC9 decoder
[ffmpeg] / libavcodec / vp3.c
index cf9c57f5faa6203ebadaaa6f6df4de177f35a42b..0e6da89abbcad811727bba6ad029b0e3c6405273 100644 (file)
@@ -451,6 +451,7 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
     int i, j;
     int current_fragment;
     int plane;
+    int plane0_num_coded_frags = 0;
 
     if (s->keyframe) {
         memset(s->superblock_coding, SB_FULLY_CODED, s->superblock_count);
@@ -544,6 +545,9 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
         int num_coded_frags = 0;
 
         for (i = sb_start; i < sb_end && get_bits_left(gb) > 0; i++) {
+            if (s->keyframe == 0 && get_bits_left(gb) < plane0_num_coded_frags >> 2) {
+                return AVERROR_INVALIDDATA;
+            }
             /* iterate through all 16 fragments in a superblock */
             for (j = 0; j < 16; j++) {
                 /* if the fragment is in bounds, check its coding status */
@@ -576,6 +580,8 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
                 }
             }
         }
+        if (!plane)
+            plane0_num_coded_frags = num_coded_frags;
         s->total_num_coded_frags += num_coded_frags;
         for (i = 0; i < 64; i++)
             s->num_coded_frags[plane][i] = num_coded_frags;
@@ -951,9 +957,11 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
     Vp3Fragment *all_fragments = s->all_fragments;
     VLC_TYPE(*vlc_table)[2] = table->table;
 
-    if (num_coeffs < 0)
+    if (num_coeffs < 0) {
         av_log(s->avctx, AV_LOG_ERROR,
                "Invalid number of coefficients at level %d\n", coeff_index);
+        return AVERROR_INVALIDDATA;
+    }
 
     if (eob_run > num_coeffs) {
         coeff_i      =
@@ -978,6 +986,9 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
             if (eob_run_get_bits[token])
                 eob_run += get_bits(gb, eob_run_get_bits[token]);
 
+            if (!eob_run)
+                eob_run = INT_MAX;
+
             // record only the number of blocks ended in this plane,
             // any spill will be recorded in the next plane.
             if (eob_run > num_coeffs - coeff_i) {