Merge commit 'f776899a17dce32ad7fb9231d98f15558f37cc3f'
[ffmpeg.git] / libavcodec / bitstream.c
index f9f2d3a..1d0e585 100644 (file)
@@ -6,20 +6,20 @@
  *
  * alternative bitstream reader & writer by Michael Niedermayer <michaelni@gmx.at>
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -28,6 +28,7 @@
  * bitstream api.
  */
 
+#include "libavutil/avassert.h"
 #include "avcodec.h"
 #include "mathops.h"
 #include "get_bits.h"
@@ -109,7 +110,7 @@ static int alloc_table(VLC *vlc, int size, int use_static)
         if (use_static)
             abort(); // cannot do anything, init_vlc() is used with too little memory
         vlc->table_allocated += (1 << vlc->bits);
-        vlc->table = av_realloc(vlc->table, sizeof(VLC_TYPE) * 2 * vlc->table_allocated);
+        vlc->table = av_realloc_f(vlc->table, vlc->table_allocated, sizeof(VLC_TYPE) * 2);
         if (!vlc->table)
             return -1;
     }
@@ -160,6 +161,8 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes,
     VLC_TYPE (*table)[2];
 
     table_size = 1 << table_nb_bits;
+    if (table_nb_bits > 30)
+       return -1;
     table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC);
     av_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size);
     if (table_index < 0)
@@ -269,11 +272,24 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
 
     vlc->bits = nb_bits;
     if (flags & INIT_VLC_USE_NEW_STATIC) {
-        if (vlc->table_size && vlc->table_size == vlc->table_allocated) {
+        VLC dyn_vlc = *vlc;
+
+        if (vlc->table_size)
             return 0;
-        } else if (vlc->table_size) {
-            abort(); // fatal error, we are called on a partially initialized table
-        }
+
+        ret = ff_init_vlc_sparse(&dyn_vlc, nb_bits, nb_codes,
+                                 bits, bits_wrap, bits_size,
+                                 codes, codes_wrap, codes_size,
+                                 symbols, symbols_wrap, symbols_size,
+                                 flags & ~INIT_VLC_USE_NEW_STATIC);
+        av_assert0(ret >= 0);
+        av_assert0(dyn_vlc.table_size <= vlc->table_allocated);
+        if (dyn_vlc.table_size < vlc->table_allocated)
+            av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", dyn_vlc.table_size, vlc->table_allocated);
+        memcpy(vlc->table, dyn_vlc.table, dyn_vlc.table_size * sizeof(*vlc->table));
+        vlc->table_size = dyn_vlc.table_size;
+        ff_free_vlc(&dyn_vlc);
+        return 0;
     } else {
         vlc->table           = NULL;
         vlc->table_allocated = 0;
@@ -284,22 +300,32 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
 
     buf = av_malloc((nb_codes + 1) * sizeof(VLCcode));
 
-    assert(symbols_size <= 2 || !symbols);
+    av_assert0(symbols_size <= 2 || !symbols);
     j = 0;
-#define COPY(condition)                                                     \
+#define COPY(condition)\
     for (i = 0; i < nb_codes; i++) {                                        \
         GET_DATA(buf[j].bits, bits, i, bits_wrap, bits_size);               \
         if (!(condition))                                                   \
             continue;                                                       \
+        if (buf[j].bits > 3*nb_bits || buf[j].bits>32) {                    \
+            av_log(NULL, AV_LOG_ERROR, "Too long VLC (%d) in init_vlc\n", buf[j].bits);\
+            av_free(buf);                                                   \
+            return -1;                                                      \
+        }                                                                   \
         GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size);            \
+        if (buf[j].code >= (1LL<<buf[j].bits)) {                            \
+            av_log(NULL, AV_LOG_ERROR, "Invalid code in init_vlc\n");       \
+            av_free(buf);                                                   \
+            return -1;                                                      \
+        }                                                                   \
         if (flags & INIT_VLC_LE)                                            \
             buf[j].code = bitswap_32(buf[j].code);                          \
         else                                                                \
             buf[j].code <<= 32 - buf[j].bits;                               \
         if (symbols)                                                        \
             GET_DATA(buf[j].symbol, symbols, i, symbols_wrap, symbols_size) \
-            else                                                            \
-                buf[j].symbol = i;                                          \
+        else                                                                \
+            buf[j].symbol = i;                                              \
         j++;                                                                \
     }
     COPY(buf[j].bits > nb_bits);
@@ -315,10 +341,6 @@ int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes,
         av_freep(&vlc->table);
         return -1;
     }
-    if ((flags & INIT_VLC_USE_NEW_STATIC) &&
-        vlc->table_size != vlc->table_allocated)
-        av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n",
-               vlc->table_size, vlc->table_allocated);
     return 0;
 }