diff options
Diffstat (limited to 'libavcodec/smacker.c')
-rw-r--r-- | libavcodec/smacker.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index df2d4c4..fa4812c 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -2,20 +2,20 @@ * Smacker decoder * Copyright (c) 2006 Konstantin Shishkov * - * 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 */ @@ -96,6 +96,10 @@ enum SmkBlockTypes { */ static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) { + if(length > 32) { + av_log(NULL, AV_LOG_ERROR, "length too long\n"); + return -1; + } if(!get_bits1(gb)){ //Leaf if(hc->current >= 256){ av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); @@ -169,7 +173,7 @@ static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, DBCtx *ctx } /** - * Store large tree as Libav's vlc codes + * Store large tree as FFmpeg's vlc codes */ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) { @@ -227,12 +231,9 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int av_log(smk->avctx, AV_LOG_ERROR, "Skipping high bytes tree\n"); } - escapes[0] = get_bits(gb, 8); - escapes[0] |= get_bits(gb, 8) << 8; - escapes[1] = get_bits(gb, 8); - escapes[1] |= get_bits(gb, 8) << 8; - escapes[2] = get_bits(gb, 8); - escapes[2] |= get_bits(gb, 8) << 8; + escapes[0] = get_bits(gb, 16); + escapes[1] = get_bits(gb, 16); + escapes[2] = get_bits(gb, 16); last[0] = last[1] = last[2] = -1; @@ -256,6 +257,11 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int if(ctx.last[0] == -1) ctx.last[0] = huff.current++; if(ctx.last[1] == -1) ctx.last[1] = huff.current++; if(ctx.last[2] == -1) ctx.last[2] = huff.current++; + if(huff.current > huff.length){ + ctx.last[0] = ctx.last[1] = ctx.last[2] = 1; + av_log(smk->avctx, AV_LOG_ERROR, "bigtree damaged\n"); + return -1; + } *recodes = huff.values; @@ -363,7 +369,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac if (avpkt->size <= 769) return 0; - smk->pic.reference = 1; + smk->pic.reference = 3; smk->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; if(avctx->reget_buffer(avctx, &smk->pic) < 0){ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); @@ -382,7 +388,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac smk->pic.pict_type = AV_PICTURE_TYPE_P; for(i = 0; i < 256; i++) - *pal++ = bytestream2_get_be24u(&gb2); + *pal++ = 0xFF << 24 | bytestream2_get_be24u(&gb2); last_reset(smk->mmap_tbl, smk->mmap_last); last_reset(smk->mclr_tbl, smk->mclr_last); @@ -517,6 +523,7 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_PAL8; + avcodec_get_frame_defaults(&c->pic); /* decode huffman trees from extradata */ if(avctx->extradata_size < 16){ @@ -655,16 +662,26 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, for(i = 0; i <= stereo; i++) *samples++ = pred[i]; for(; i < unp_size / 2; i++) { + if(get_bits_left(&gb)<0) + return -1; if(i & stereo) { if(vlc[2].table) res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3); else res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } val = h[2].values[res]; if(vlc[3].table) res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3); else res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } val |= h[3].values[res] << 8; pred[1] += sign_extend(val, 16); *samples++ = av_clip_int16(pred[1]); @@ -673,11 +690,19 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); else res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } val = h[0].values[res]; if(vlc[1].table) res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); else res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } val |= h[1].values[res] << 8; pred[0] += sign_extend(val, 16); *samples++ = av_clip_int16(pred[0]); @@ -689,11 +714,17 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, for(i = 0; i <= stereo; i++) *samples8++ = pred[i]; for(; i < unp_size; i++) { + if(get_bits_left(&gb)<0) + return -1; if(i & stereo){ if(vlc[1].table) res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); else res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } pred[1] += sign_extend(h[1].values[res], 8); *samples8++ = av_clip_uint8(pred[1]); } else { @@ -701,6 +732,10 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); else res = 0; + if (res < 0) { + av_log(avctx, AV_LOG_ERROR, "invalid vlc\n"); + return AVERROR_INVALIDDATA; + } pred[0] += sign_extend(h[0].values[res], 8); *samples8++ = av_clip_uint8(pred[0]); } |