smacker.c (libav-12.2) | : | smacker.c (libav-12.3) | ||
---|---|---|---|---|
skipping to change at line 45 | skipping to change at line 45 | |||
#define BITSTREAM_READER_LE | #define BITSTREAM_READER_LE | |||
#include "avcodec.h" | #include "avcodec.h" | |||
#include "bytestream.h" | #include "bytestream.h" | |||
#include "get_bits.h" | #include "get_bits.h" | |||
#include "internal.h" | #include "internal.h" | |||
#include "mathops.h" | #include "mathops.h" | |||
#define SMKTREE_BITS 9 | #define SMKTREE_BITS 9 | |||
#define SMK_NODE 0x80000000 | #define SMK_NODE 0x80000000 | |||
#define SMKTREE_DECODE_MAX_RECURSION 32 | ||||
#define SMKTREE_DECODE_BIG_MAX_RECURSION 500 | ||||
typedef struct SmackVContext { | typedef struct SmackVContext { | |||
AVCodecContext *avctx; | AVCodecContext *avctx; | |||
AVFrame *pic; | AVFrame *pic; | |||
int *mmap_tbl, *mclr_tbl, *full_tbl, *type_tbl; | int *mmap_tbl, *mclr_tbl, *full_tbl, *type_tbl; | |||
int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; | int mmap_last[3], mclr_last[3], full_last[3], type_last[3]; | |||
} SmackVContext; | } SmackVContext; | |||
/** | /** | |||
skipping to change at line 97 | skipping to change at line 99 | |||
SMK_BLK_MONO = 0, | SMK_BLK_MONO = 0, | |||
SMK_BLK_FULL = 1, | SMK_BLK_FULL = 1, | |||
SMK_BLK_SKIP = 2, | SMK_BLK_SKIP = 2, | |||
SMK_BLK_FILL = 3 }; | SMK_BLK_FILL = 3 }; | |||
/** | /** | |||
* Decode local frame tree | * Decode local frame tree | |||
*/ | */ | |||
static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t pref ix, int length) | static int smacker_decode_tree(GetBitContext *gb, HuffContext *hc, uint32_t pref ix, int length) | |||
{ | { | |||
if (length > SMKTREE_DECODE_MAX_RECURSION) { | ||||
av_log(NULL, AV_LOG_ERROR, "Maximum tree recursion level exceeded.\n"); | ||||
return AVERROR_INVALIDDATA; | ||||
} | ||||
if(!get_bits1(gb)){ //Leaf | if(!get_bits1(gb)){ //Leaf | |||
if(hc->current >= 256){ | if(hc->current >= 256){ | |||
av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); | av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); | |||
return -1; | return -1; | |||
} | } | |||
if(length){ | if(length){ | |||
hc->bits[hc->current] = prefix; | hc->bits[hc->current] = prefix; | |||
hc->lengths[hc->current] = length; | hc->lengths[hc->current] = length; | |||
} else { | } else { | |||
hc->bits[hc->current] = 0; | hc->bits[hc->current] = 0; | |||
skipping to change at line 127 | skipping to change at line 134 | |||
r = smacker_decode_tree(gb, hc, prefix, length); | r = smacker_decode_tree(gb, hc, prefix, length); | |||
if(r) | if(r) | |||
return r; | return r; | |||
return smacker_decode_tree(gb, hc, prefix | (1 << (length - 1)), length) ; | return smacker_decode_tree(gb, hc, prefix | (1 << (length - 1)), length) ; | |||
} | } | |||
} | } | |||
/** | /** | |||
* Decode header tree | * Decode header tree | |||
*/ | */ | |||
static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, DBCtx *ctx | static int smacker_decode_bigtree(GetBitContext *gb, HuffContext *hc, | |||
) | DBCtx *ctx, int length) | |||
{ | { | |||
// Larger length can cause segmentation faults due to too deep recursion. | ||||
if (length > SMKTREE_DECODE_BIG_MAX_RECURSION) { | ||||
av_log(NULL, AV_LOG_ERROR, "Maximum bigtree recursion level exceeded.\n" | ||||
); | ||||
return AVERROR_INVALIDDATA; | ||||
} | ||||
if (hc->current + 1 >= hc->length) { | if (hc->current + 1 >= hc->length) { | |||
av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); | av_log(NULL, AV_LOG_ERROR, "Tree size exceeded!\n"); | |||
return -1; | return -1; | |||
} | } | |||
if(!get_bits1(gb)){ //Leaf | if(!get_bits1(gb)){ //Leaf | |||
int val, i1, i2; | int val, i1, i2; | |||
i1 = ctx->v1->table ? get_vlc2(gb, ctx->v1->table, SMKTREE_BITS, 3) : 0; | 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; | i2 = ctx->v2->table ? get_vlc2(gb, ctx->v2->table, SMKTREE_BITS, 3) : 0; | |||
if (i1 < 0 || i2 < 0) | if (i1 < 0 || i2 < 0) | |||
return -1; | return -1; | |||
skipping to change at line 157 | skipping to change at line 171 | |||
ctx->last[2] = hc->current; | ctx->last[2] = hc->current; | |||
val = 0; | val = 0; | |||
} | } | |||
hc->values[hc->current++] = val; | hc->values[hc->current++] = val; | |||
return 1; | return 1; | |||
} else { //Node | } else { //Node | |||
int r = 0, r_new, t; | int r = 0, r_new, t; | |||
t = hc->current++; | t = hc->current++; | |||
r = smacker_decode_bigtree(gb, hc, ctx); | r = smacker_decode_bigtree(gb, hc, ctx, length + 1); | |||
if(r < 0) | if(r < 0) | |||
return r; | return r; | |||
hc->values[t] = SMK_NODE | r; | hc->values[t] = SMK_NODE | r; | |||
r++; | r++; | |||
r_new = smacker_decode_bigtree(gb, hc, ctx); | r_new = smacker_decode_bigtree(gb, hc, ctx, length + 1); | |||
if (r_new < 0) | if (r_new < 0) | |||
return r_new; | return r_new; | |||
return r + r_new; | return r + r_new; | |||
} | } | |||
} | } | |||
/** | /** | |||
* Store large tree as Libav's vlc codes | * Store large tree as Libav's vlc codes | |||
*/ | */ | |||
static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) | static int smacker_decode_header_tree(SmackVContext *smk, GetBitContext *gb, int **recodes, int *last, int size) | |||
skipping to change at line 262 | skipping to change at line 276 | |||
huff.length = ((size + 3) >> 2) + 4; | huff.length = ((size + 3) >> 2) + 4; | |||
huff.maxlength = 0; | huff.maxlength = 0; | |||
huff.current = 0; | huff.current = 0; | |||
huff.values = av_mallocz(huff.length * sizeof(int)); | huff.values = av_mallocz(huff.length * sizeof(int)); | |||
if (!huff.values) { | if (!huff.values) { | |||
err = AVERROR(ENOMEM); | err = AVERROR(ENOMEM); | |||
goto error; | goto error; | |||
} | } | |||
if (smacker_decode_bigtree(gb, &huff, &ctx) < 0) | if (smacker_decode_bigtree(gb, &huff, &ctx, 0) < 0) | |||
err = -1; | err = -1; | |||
skip_bits1(gb); | skip_bits1(gb); | |||
if(ctx.last[0] == -1) ctx.last[0] = huff.current++; | if(ctx.last[0] == -1) ctx.last[0] = huff.current++; | |||
if(ctx.last[1] == -1) ctx.last[1] = 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[2] == -1) ctx.last[2] = huff.current++; | |||
if (ctx.last[0] >= huff.length || | if (ctx.last[0] >= huff.length || | |||
ctx.last[1] >= huff.length || | ctx.last[1] >= huff.length || | |||
ctx.last[2] >= huff.length) { | ctx.last[2] >= huff.length) { | |||
av_log(smk->avctx, AV_LOG_ERROR, "Huffman codes out of range\n"); | av_log(smk->avctx, AV_LOG_ERROR, "Huffman codes out of range\n"); | |||
err = AVERROR_INVALIDDATA; | err = AVERROR_INVALIDDATA; | |||
End of changes. 7 change blocks. | ||||
5 lines changed or deleted | 19 lines changed or added |