diff options
Diffstat (limited to 'libavcodec/bitstream.c')
-rw-r--r-- | libavcodec/bitstream.c | 58 |
1 files changed, 40 insertions, 18 deletions
diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index 197e07f411..23bea43ac7 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -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" @@ -107,9 +108,9 @@ static int alloc_table(VLC *vlc, int size, int use_static) vlc->table_size += size; if (vlc->table_size > vlc->table_allocated) { if (use_static) - return AVERROR_BUG; + 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 AVERROR(ENOMEM); } @@ -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) { - return AVERROR_BUG; - } + + 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 ret; } - 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; } |