X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fsmacker.c;h=bcdf792e3031543a963be7962ad8a56b648733f1;hb=c325b5054f7cedb541ebd2f36059d7315a965d5f;hp=fa1bdf6c8bd5a6ef21958c046bfa58288b294023;hpb=e5a389a1b70a32a56aa83377e88bf718251aa8f0;p=ffmpeg diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index fa1bdf6c8bd..bcdf792e303 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -35,6 +35,7 @@ #define ALT_BITSTREAM_READER_LE #include "bitstream.h" +#include "bytestream.h" #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 @@ -201,7 +202,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int if(get_bits1(gb)) { smacker_decode_tree(gb, &tmp1, 0, 0); - get_bits1(gb); + skip_bits1(gb); res = init_vlc(&vlc[0], SMKTREE_BITS, tmp1.length, tmp1.lengths, sizeof(int), sizeof(int), tmp1.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); @@ -214,7 +215,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int } if(get_bits1(gb)){ smacker_decode_tree(gb, &tmp2, 0, 0); - get_bits1(gb); + skip_bits1(gb); res = init_vlc(&vlc[1], SMKTREE_BITS, tmp2.length, tmp2.lengths, sizeof(int), sizeof(int), tmp2.bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); @@ -250,7 +251,7 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int huff.values = av_mallocz(huff.length * sizeof(int)); smacker_decode_bigtree(gb, &huff, &ctx); - get_bits1(gb); + skip_bits1(gb); 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++; @@ -290,7 +291,7 @@ static int decode_header_trees(SmackVContext *smk) { } else { smacker_decode_header_tree(smk, &gb, &smk->mmap_tbl, smk->mmap_last, mmap_size); } - if(!get_bits(&gb, 1)) { + if(!get_bits1(&gb)) { av_log(smk->avctx, AV_LOG_INFO, "Skipping MCLR tree\n"); smk->mclr_tbl = av_malloc(sizeof(int) * 2); smk->mclr_tbl[0] = 0; @@ -298,7 +299,7 @@ static int decode_header_trees(SmackVContext *smk) { } else { smacker_decode_header_tree(smk, &gb, &smk->mclr_tbl, smk->mclr_last, mclr_size); } - if(!get_bits(&gb, 1)) { + if(!get_bits1(&gb)) { av_log(smk->avctx, AV_LOG_INFO, "Skipping FULL tree\n"); smk->full_tbl = av_malloc(sizeof(int) * 2); smk->full_tbl[0] = 0; @@ -306,7 +307,7 @@ static int decode_header_trees(SmackVContext *smk) { } else { smacker_decode_header_tree(smk, &gb, &smk->full_tbl, smk->full_last, full_size); } - if(!get_bits(&gb, 1)) { + if(!get_bits1(&gb)) { av_log(smk->avctx, AV_LOG_INFO, "Skipping TYPE tree\n"); smk->type_tbl = av_malloc(sizeof(int) * 2); smk->type_tbl[0] = 0; @@ -344,7 +345,7 @@ static av_always_inline int smk_get_code(GetBitContext *gb, int *recode, int *la return v; } -static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) +static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size) { SmackVContext * const smk = avctx->priv_data; uint8_t *out; @@ -354,7 +355,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 int i; int stride; - if(buf_size == 769) + if(buf_size <= 769) return 0; if(smk->pic.data[0]) avctx->release_buffer(avctx, &smk->pic); @@ -367,7 +368,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 } /* make the palette available on the way out */ - out = buf + 1; pal = (uint32_t*)smk->pic.data[1]; smk->pic.palette_has_changed = buf[0] & 1; smk->pic.key_frame = !!(buf[0] & 2); @@ -376,19 +376,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 else smk->pic.pict_type = FF_P_TYPE; - for(i = 0; i < 256; i++) { - int r, g, b; - r = *out++; - g = *out++; - b = *out++; - *pal++ = (r << 16) | (g << 8) | b; - } + buf++; + for(i = 0; i < 256; i++) + *pal++ = bytestream_get_be24(&buf); + buf_size -= 769; last_reset(smk->mmap_tbl, smk->mmap_last); last_reset(smk->mclr_tbl, smk->mclr_last); last_reset(smk->full_tbl, smk->full_last); last_reset(smk->type_tbl, smk->type_last); - init_get_bits(&gb, buf + 769, (buf_size - 769) * 8); + init_get_bits(&gb, buf, buf_size * 8); blk = 0; bw = avctx->width >> 2; @@ -460,8 +457,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 case 2: for(i = 0; i < 2; i++) { uint16_t pix1, pix2; - pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last); pix2 = smk_get_code(&gb, smk->full_tbl, smk->full_last); + pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last); AV_WL16(out,pix1); AV_WL16(out+2,pix2); out += stride; @@ -509,7 +506,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 * Init smacker decoder * */ -static int decode_init(AVCodecContext *avctx) +static av_cold int decode_init(AVCodecContext *avctx) { SmackVContext * const c = avctx->priv_data; @@ -543,7 +540,7 @@ static int decode_init(AVCodecContext *avctx) * Uninit smacker decoder * */ -static int decode_end(AVCodecContext *avctx) +static av_cold int decode_end(AVCodecContext *avctx) { SmackVContext * const smk = avctx->priv_data; @@ -559,15 +556,17 @@ static int decode_end(AVCodecContext *avctx) } -static int smka_decode_init(AVCodecContext *avctx) +static av_cold int smka_decode_init(AVCodecContext *avctx) { + avctx->sample_fmt = SAMPLE_FMT_S16; + avctx->channel_layout = (avctx->channels==2) ? CH_LAYOUT_STEREO : CH_LAYOUT_MONO; return 0; } /** * Decode Smacker audio data */ -static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size) +static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size) { GetBitContext gb; HuffContext h[4]; @@ -590,6 +589,10 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, } stereo = get_bits1(&gb); bits = get_bits1(&gb); + if (unp_size & 0xC0000000 || (unp_size << !bits) > *data_size) { + av_log(avctx, AV_LOG_ERROR, "Frame is too large to fit in buffer\n"); + return -1; + } memset(vlc, 0, sizeof(VLC) * 4); memset(h, 0, sizeof(HuffContext) * 4); @@ -601,9 +604,9 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, h[i].bits = av_mallocz(256 * 4); h[i].lengths = av_mallocz(256 * sizeof(int)); h[i].values = av_mallocz(256 * sizeof(int)); - get_bits1(&gb); + skip_bits1(&gb); smacker_decode_tree(&gb, &h[i], 0, 0); - get_bits1(&gb); + skip_bits1(&gb); if(h[i].current > 1) { res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length, h[i].lengths, sizeof(int), sizeof(int), @@ -696,7 +699,8 @@ AVCodec smacker_decoder = { decode_init, NULL, decode_end, - decode_frame + decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Smacker video"), }; AVCodec smackaud_decoder = { @@ -707,6 +711,7 @@ AVCodec smackaud_decoder = { smka_decode_init, NULL, NULL, - smka_decode_frame + smka_decode_frame, + .long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), };