diff options
Diffstat (limited to 'libavcodec/cavsdec.c')
-rw-r--r-- | libavcodec/cavsdec.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index af0309c41b..34eeabdae2 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -2,20 +2,20 @@ * Chinese AVS video (AVS1-P2, JiZhun profile) decoder. * Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.de> * - * 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 */ @@ -25,6 +25,7 @@ * @author Stefan Gehrer <stefan.gehrer@gmx.de> */ +#include "libavutil/avassert.h" #include "avcodec.h" #include "get_bits.h" #include "golomb.h" @@ -544,7 +545,8 @@ static inline int dequant(AVSContext *h, DCTELEM *level_buf, uint8_t *run_buf, static int decode_residual_block(AVSContext *h, GetBitContext *gb, const struct dec_2dvlc *r, int esc_golomb_order, int qp, uint8_t *dst, int stride) { - int i, level_code, esc_code, level, run, mask; + int i, esc_code, level, mask; + unsigned int level_code, run; DCTELEM level_buf[65]; uint8_t run_buf[65]; DCTELEM *block = h->block; @@ -553,20 +555,20 @@ static int decode_residual_block(AVSContext *h, GetBitContext *gb, level_code = get_ue_code(gb,r->golomb_order); if(level_code >= ESCAPE_CODE) { run = ((level_code - ESCAPE_CODE) >> 1) + 1; + if(run > 64) + return -1; esc_code = get_ue_code(gb,esc_golomb_order); level = esc_code + (run > r->max_run ? 1 : r->level_add[run]); while(level > r->inc_limit) r++; mask = -(level_code & 1); level = (level^mask) - mask; - } else if (level_code >= 0) { + } else { level = r->rltab[level_code][0]; if(!level) //end of block signal break; run = r->rltab[level_code][1]; r += r->rltab[level_code][2]; - } else { - break; } level_buf[i] = level; run_buf[i] = run; @@ -594,7 +596,7 @@ static inline int decode_residual_inter(AVSContext *h) { /* get coded block pattern */ int cbp= get_ue_golomb(&h->s.gb); - if(cbp > 63){ + if(cbp > 63U){ av_log(h->s.avctx, AV_LOG_ERROR, "illegal inter cbp\n"); return -1; } @@ -663,7 +665,7 @@ static int decode_mb_i(AVSContext *h, int cbp_code) { /* get coded block pattern */ if(h->pic_type == AV_PICTURE_TYPE_I) cbp_code = get_ue_golomb(gb); - if(cbp_code > 63){ + if(cbp_code > 63U){ av_log(h->s.avctx, AV_LOG_ERROR, "illegal intra cbp\n"); return -1; } @@ -748,7 +750,7 @@ static void decode_mb_p(AVSContext *h, enum cavs_mb mb_type) { h->col_type_base[h->mbidx] = mb_type; } -static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type) { +static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type) { int block; enum cavs_sub_mb sub_type[4]; int flags; @@ -819,7 +821,11 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type) { } break; default: - assert((mb_type > B_SYM_16X16) && (mb_type < B_8X8)); + if (mb_type <= B_SYM_16X16) { + av_log(h->s.avctx, AV_LOG_ERROR, "Invalid mb_type %d in B frame\n", mb_type); + return AVERROR_INVALIDDATA; + } + av_assert2(mb_type < B_8X8); flags = ff_cavs_partition_flags[mb_type]; if(mb_type & 1) { /* 16x8 macroblock types */ if(flags & FWD0) @@ -854,6 +860,8 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type) { if(mb_type != B_SKIP) decode_residual_inter(h); ff_cavs_filter(h,mb_type); + + return 0; } /***************************************************************************** @@ -865,6 +873,10 @@ static void decode_mb_b(AVSContext *h, enum cavs_mb mb_type) { static inline int decode_slice_header(AVSContext *h, GetBitContext *gb) { if(h->stc > 0xAF) av_log(h->s.avctx, AV_LOG_ERROR, "unexpected start code 0x%02x\n", h->stc); + + if (h->stc >= h->mb_height) + return -1; + h->mby = h->stc; h->mbidx = h->mby*h->mb_width; @@ -1069,6 +1081,10 @@ static int decode_seq_header(AVSContext *h) { av_log_missing_feature(s, "Width/height changing in CAVS", 0); return AVERROR_PATCHWELCOME; } + if (width <= 0 || height <= 0) { + av_log(s, AV_LOG_ERROR, "Dimensions invalid\n"); + return AVERROR_INVALIDDATA; + } s->width = width; s->height = height; @@ -1143,6 +1159,8 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, *got_frame = 0; if(!h->got_keyframe) break; + if(!h->top_qp) + break; init_get_bits(&s->gb, buf_ptr, input_size); h->stc = stc; if(decode_pic(h)) |