X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fsmacker.c;h=75ab5d71205eb69afa0f7e1c777ca7b4e806cc1d;hb=bc70684e74a185d7b80c8b80bdedda659cb581b8;hp=e6b163722a4c332820e8105faa0ba2f7cd13f351;hpb=01dbcbb37a30b77dcdc7b2d9ed6a4fcccf4f4eec;p=ffmpeg diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index e6b163722a4..75ab5d71205 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -33,19 +33,27 @@ #include "libavutil/channel_layout.h" -#define BITSTREAM_READER_LE #include "avcodec.h" -#include "bytestream.h" -#include "get_bits.h" -#include "internal.h" -#include "mathops.h" #define SMKTREE_BITS 9 #define SMK_NODE 0x80000000 -#define SMKTREE_DECODE_MAX_RECURSION 32 +#define SMKTREE_DECODE_MAX_RECURSION FFMIN(32, 3 * SMKTREE_BITS) #define SMKTREE_DECODE_BIG_MAX_RECURSION 500 +/* The maximum possible unchecked overread happens in decode_header_trees: + * Decoding the MMAP tree can overread by 6 * SMKTREE_BITS + 1, followed by + * three get_bits1, followed by at most 2 + 3 * 16 read bits when reading + * the TYPE tree before the next check. 64 is because of 64 bit reads. */ +#if (6 * SMKTREE_BITS + 1 + 3 + (2 + 3 * 16) + 64) <= 8 * AV_INPUT_BUFFER_PADDING_SIZE +#define UNCHECKED_BITSTREAM_READER 1 +#endif +#define BITSTREAM_READER_LE +#include "bytestream.h" +#include "get_bits.h" +#include "internal.h" +#include "mathops.h" + typedef struct SmackVContext { AVCodecContext *avctx; AVFrame *pic; @@ -54,21 +62,25 @@ typedef struct SmackVContext { int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; } SmackVContext; +typedef struct HuffEntry { + uint8_t value; + uint8_t length; +} HuffEntry; + /** * Context used for code reconstructing */ typedef struct HuffContext { - int length; int current; - uint32_t *bits; - int *lengths; - int *values; + HuffEntry entries[256]; } HuffContext; /* common parameters used for decode_bigtree */ typedef struct DBCtx { + int current, length; + int *values; VLC *v1, *v2; - int *recode1, *recode2; + uint8_t vals[2]; int escapes[3]; int *last; } DBCtx; @@ -92,8 +104,11 @@ enum SmkBlockTypes { /** * Decode local frame tree + * + * Can read SMKTREE_DECODE_MAX_RECURSION before the first check; + * does not overread gb on success. */ -static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t prefix, int length) +static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, int length) { if (length > SMKTREE_DECODE_MAX_RECURSION || length > 3 * SMKTREE_BITS) { av_log(NULL, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n"); @@ -101,35 +116,30 @@ static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t pref } if(!get_bits1(gb)){ //Leaf - if(hc->current >= hc->length){ + if (hc->current >= 256) { av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); return AVERROR_INVALIDDATA; } - if(length){ - hc->bits[hc->current] = prefix; - hc->lengths[hc->current] = length; - } else { - hc->bits[hc->current] = 0; - hc->lengths[hc->current] = 0; - } - hc->values[hc->current] = get_bits(gb, 8); - hc->current++; + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + hc->entries[hc->current++] = (HuffEntry){ get_bits(gb, 8), length }; return 0; } else { //Node int r; length++; - r = smacker_decode_tree(gb, hc, prefix, length); + r = smacker_decode_tree(gb, hc, length); if(r) return r; - return smacker_decode_tree(gb, hc, prefix | (1U << (length - 1)), length); + return smacker_decode_tree(gb, hc, length); } } /** * Decode header tree + * + * Checks before the first read, can overread by 6 * SMKTREE_BITS on success. */ -static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, - DBCtx *ctx, int length) +static int smacker_decode_bigtree(GetBitContext *gb, DBCtx *ctx, int length) { // Larger length can cause segmentation faults due to too deep recursion. if (length > SMKTREE_DECODE_BIG_MAX_RECURSION) { @@ -137,40 +147,42 @@ static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, return AVERROR_INVALIDDATA; } - if (hc->current >= hc->length) { + if (ctx->current >= ctx->length) { av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); return AVERROR_INVALIDDATA; } + if (get_bits_left(gb) <= 0) + return AVERROR_INVALIDDATA; if(!get_bits1(gb)){ //Leaf int val, i1, i2; - i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) : 0; - i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) : 0; - if (i1 < 0 || i2 < 0) - return AVERROR_INVALIDDATA; - val = ctx->recode1[i1] | (ctx->recode2[i2] << 8); + i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) + : ctx->vals[0]; + i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) + : ctx->vals[1]; + val = i1 | (i2 << 8); if(val == ctx->escapes[0]) { - ctx->last[0] = hc->current; + ctx->last[0] = ctx->current; val = 0; } else if(val == ctx->escapes[1]) { - ctx->last[1] = hc->current; + ctx->last[1] = ctx->current; val = 0; } else if(val == ctx->escapes[2]) { - ctx->last[2] = hc->current; + ctx->last[2] = ctx->current; val = 0; } - hc->values[hc->current++] = val; + ctx->values[ctx->current++] = val; return 1; } else { //Node int r = 0, r_new, t; - t = hc->current++; - r = smacker_decode_bigtree(gb, hc, ctx, length + 1); + t = ctx->current++; + r = smacker_decode_bigtree(gb, ctx, length + 1); if(r < 0) return r; - hc->values[t] = SMK_NODE | r; + ctx->values[t] = SMK_NODE | r; r++; - r_new = smacker_decode_bigtree(gb, hc, ctx, length + 1); + r_new = smacker_decode_bigtree(gb, ctx, length + 1); if (r_new < 0) return r_new; return r + r_new; @@ -179,11 +191,12 @@ static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, /** * Store large tree as FFmpeg's vlc codes + * + * Can read FFMAX(1 + SMKTREE_DECODE_MAX_RECURSION, 2 + 3 * 16) bits + * before the first check; can overread by 6 * SMKTREE_BITS + 1 on success. */ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) { - HuffContext huff; - HuffContext h[2] = { 0 }; VLC vlc[2] = { { 0 } }; int escapes[3]; DBCtx ctx; @@ -195,34 +208,29 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int } for (int i = 0; i < 2; i++) { - h[i].length = 256; - h[i].current = 0; - h[i].bits = av_mallocz(256 * sizeof(h[i].bits[0])); - h[i].lengths = av_mallocz(256 * sizeof(h[i].lengths[0])); - h[i].values = av_mallocz(256 * sizeof(h[i].values[0])); - if (!h[i].bits || !h[i].lengths || !h[i].values) { - err = AVERROR(ENOMEM); - goto error; - } + HuffContext h; + h.current = 0; if (!get_bits1(gb)) { + ctx.vals[i] = 0; av_log(smk->avctx, AV_LOG_ERROR, "Skipping %s bytes tree\n", i ? "high" : "low"); continue; } - err = smacker_decode_tree(gb, &h[i], 0, 0); + err = smacker_decode_tree(gb, &h, 0); if (err < 0) goto error; skip_bits1(gb); - if (h[i].current > 1) { - err = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length, - INIT_VLC_DEFAULT_SIZES(h[i].lengths), - INIT_VLC_DEFAULT_SIZES(h[i].bits), - INIT_VLC_LE); + if (h.current > 1) { + err = ff_init_vlc_from_lengths(&vlc[i], SMKTREE_BITS, h.current, + &h.entries[0].length, sizeof(*h.entries), + &h.entries[0].value, sizeof(*h.entries), 1, + 0, INIT_VLC_OUTPUT_LE, smk->avctx); if (err < 0) { av_log(smk->avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); goto error; } - } + } else + ctx.vals[i] = h.entries[0].value; } escapes[0] = get_bits(gb, 16); @@ -236,35 +244,28 @@ static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int ctx.escapes[2] = escapes[2]; ctx.v1 = &vlc[0]; ctx.v2 = &vlc[1]; - ctx.recode1 = h[0].values; - ctx.recode2 = h[1].values; ctx.last = last; - - huff.length = (size + 3) >> 2; - huff.current = 0; - huff.values = av_mallocz_array(huff.length + 3, sizeof(huff.values[0])); - if (!huff.values) { + ctx.length = (size + 3) >> 2; + ctx.current = 0; + ctx.values = av_malloc_array(ctx.length + 3, sizeof(ctx.values[0])); + if (!ctx.values) { err = AVERROR(ENOMEM); goto error; } - *recodes = huff.values; + *recodes = ctx.values; - err = smacker_decode_bigtree(gb, &huff, &ctx, 0); + err = smacker_decode_bigtree(gb, &ctx, 0); if (err < 0) goto error; 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++; + if (ctx.last[0] == -1) ctx.last[0] = ctx.current++; + if (ctx.last[1] == -1) ctx.last[1] = ctx.current++; + if (ctx.last[2] == -1) ctx.last[2] = ctx.current++; err = 0; error: for (int i = 0; i < 2; i++) { - if (vlc[i].table) - ff_free_vlc(&vlc[i]); - av_free(h[i].bits); - av_free(h[i].lengths); - av_free(h[i].values); + ff_free_vlc(&vlc[i]); } return err; @@ -336,7 +337,7 @@ static int decode_header_trees(SmackVContext *smk) { if (ret < 0) return ret; } - if (skip == 4) + if (skip == 4 || get_bits_left(&gb) < 0) return AVERROR_INVALIDDATA; return 0; @@ -346,7 +347,8 @@ static av_always_inline void last_reset(int *recode, int *last) { recode[last[0]] = recode[last[1]] = recode[last[2]] = 0; } -/* get code and update history */ +/* Get code and update history. + * Checks before reading, does not overread. */ static av_always_inline int smk_get_code(GetBitContext *gb, int *recode, int *last) { register int *table = recode; int v; @@ -445,6 +447,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, case SMK_BLK_FULL: mode = 0; if(avctx->codec_tag == MKTAG('S', 'M', 'K', '4')) { // In case of Smacker v4 we have three modes + if (get_bits_left(&gb) < 1) + return AVERROR_INVALIDDATA; if(get_bits1(&gb)) mode = 1; else if(get_bits1(&gb)) mode = 2; } @@ -552,7 +556,7 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); /* decode huffman trees from extradata */ - if(avctx->extradata_size < 16){ + if (avctx->extradata_size <= 16){ av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n"); return AVERROR(EINVAL); } @@ -588,15 +592,14 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; GetBitContext gb; - HuffContext h[4] = { { 0 } }; VLC vlc[4] = { { 0 } }; int16_t *samples; uint8_t *samples8; - int val; + uint8_t values[4]; int i, res, ret; int unp_size; int bits, stereo; - int pred[2] = {0, 0}; + unsigned pred[2], val; if (buf_size <= 4) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); @@ -643,87 +646,48 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, // Initialize for(i = 0; i < (1 << (bits + stereo)); i++) { - h[i].length = 256; - h[i].current = 0; - h[i].bits = av_mallocz(256 * 4); - h[i].lengths = av_mallocz(256 * sizeof(int)); - h[i].values = av_mallocz(256 * sizeof(int)); - if (!h[i].bits || !h[i].lengths || !h[i].values) { - ret = AVERROR(ENOMEM); - goto error; - } + HuffContext h; + h.current = 0; skip_bits1(&gb); - if ((ret = smacker_decode_tree(&gb, &h[i], 0, 0)) < 0) + if ((ret = smacker_decode_tree(&gb, &h, 0)) < 0) goto error; skip_bits1(&gb); - if(h[i].current > 1) { - ret = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length, - h[i].lengths, sizeof(int), sizeof(int), - h[i].bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE); + if (h.current > 1) { + ret = ff_init_vlc_from_lengths(&vlc[i], SMKTREE_BITS, h.current, + &h.entries[0].length, sizeof(*h.entries), + &h.entries[0].value, sizeof(*h.entries), 1, + 0, INIT_VLC_OUTPUT_LE, avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n"); goto error; } - } + } else + values[i] = h.entries[0].value; } /* this codec relies on wraparound instead of clipping audio */ if(bits) { //decode 16-bit data for(i = stereo; i >= 0; i--) - pred[i] = sign_extend(av_bswap16(get_bits(&gb, 16)), 16); + pred[i] = av_bswap16(get_bits(&gb, 16)); for(i = 0; i <= stereo; i++) *samples++ = pred[i]; for(; i < unp_size / 2; i++) { + unsigned idx = 2 * (i & stereo); if (get_bits_left(&gb) < 0) { ret = AVERROR_INVALIDDATA; goto error; } - 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"); - ret = AVERROR_INVALIDDATA; - goto error; - } - 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"); - ret = AVERROR_INVALIDDATA; - goto error; - } - val |= h[3].values[res] << 8; - pred[1] += (unsigned)sign_extend(val, 16); - *samples++ = pred[1]; - } else { - if(vlc[0].table) - 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"); - ret = AVERROR_INVALIDDATA; - goto error; - } - 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"); - ret = AVERROR_INVALIDDATA; - goto error; - } - val |= h[1].values[res] << 8; - pred[0] += (unsigned)sign_extend(val, 16); - *samples++ = pred[0]; - } + if (vlc[idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val = res; + if (vlc[++idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val |= res << 8; + pred[idx / 2] += val; + *samples++ = pred[idx / 2]; } } else { //8-bit data for(i = stereo; i >= 0; i--) @@ -731,35 +695,17 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, for(i = 0; i <= stereo; i++) *samples8++ = pred[i]; for(; i < unp_size; i++) { + unsigned idx = i & stereo; if (get_bits_left(&gb) < 0) { ret = AVERROR_INVALIDDATA; goto error; } - 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"); - ret = AVERROR_INVALIDDATA; - goto error; - } - pred[1] += sign_extend(h[1].values[res], 8); - *samples8++ = pred[1]; - } else { - if(vlc[0].table) - 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"); - ret = AVERROR_INVALIDDATA; - goto error; - } - pred[0] += sign_extend(h[0].values[res], 8); - *samples8++ = pred[0]; - } + if (vlc[idx].table) + val = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + val = values[idx]; + pred[idx] += val; + *samples8++ = pred[idx]; } } @@ -768,17 +714,13 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, error: for(i = 0; i < 4; i++) { - if(vlc[i].table) - ff_free_vlc(&vlc[i]); - av_free(h[i].bits); - av_free(h[i].lengths); - av_free(h[i].values); + ff_free_vlc(&vlc[i]); } return ret; } -AVCodec ff_smacker_decoder = { +const AVCodec ff_smacker_decoder = { .name = "smackvid", .long_name = NULL_IF_CONFIG_SMALL("Smacker video"), .type = AVMEDIA_TYPE_VIDEO, @@ -788,10 +730,10 @@ AVCodec ff_smacker_decoder = { .close = decode_end, .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; -AVCodec ff_smackaud_decoder = { +const AVCodec ff_smackaud_decoder = { .name = "smackaud", .long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), .type = AVMEDIA_TYPE_AUDIO, @@ -799,4 +741,5 @@ AVCodec ff_smackaud_decoder = { .init = smka_decode_init, .decode = smka_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, };