diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2011-10-11 22:06:52 +0400 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2011-10-28 19:47:28 +0400 |
commit | a4c32c9a63142b602820800742f2d543b58cd278 (patch) | |
tree | 488450f2bb5caf4c82c901a4ec526047dec00084 /libavcodec/apedec.c | |
parent | fd244ae3a068f4f480e967e8e522f69ef6968c69 (diff) |
apedec: check for input buffer overflow while reading frame header
Diffstat (limited to 'libavcodec/apedec.c')
-rw-r--r-- | libavcodec/apedec.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index ed9073cf9b..ef990bf693 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -471,9 +471,11 @@ static void entropy_decode(APEContext *ctx, int blockstodecode, int stereo) range_dec_normalize(ctx); /* normalize to use up all bytes */ } -static void init_entropy_decoder(APEContext *ctx) +static int init_entropy_decoder(APEContext *ctx) { /* Read the CRC */ + if (ctx->data_end - ctx->ptr < 6) + return AVERROR_INVALIDDATA; ctx->CRC = bytestream_get_be32(&ctx->ptr); /* Read the frame flags if they exist */ @@ -481,6 +483,8 @@ static void init_entropy_decoder(APEContext *ctx) if ((ctx->fileversion > 3820) && (ctx->CRC & 0x80000000)) { ctx->CRC &= ~0x80000000; + if (ctx->data_end - ctx->ptr < 6) + return AVERROR_INVALIDDATA; ctx->frameflags = bytestream_get_be32(&ctx->ptr); } @@ -497,6 +501,8 @@ static void init_entropy_decoder(APEContext *ctx) ctx->ptr++; range_start_decoding(ctx); + + return 0; } static const int32_t initial_coeffs[4] = { @@ -738,10 +744,11 @@ static void ape_apply_filters(APEContext *ctx, int32_t *decoded0, } } -static void init_frame_decoder(APEContext *ctx) +static int init_frame_decoder(APEContext *ctx) { - int i; - init_entropy_decoder(ctx); + int i, ret; + if ((ret = init_entropy_decoder(ctx)) < 0) + return ret; init_predictor_decoder(ctx); for (i = 0; i < APE_FILTER_LEVELS; i++) { @@ -750,6 +757,7 @@ static void init_frame_decoder(APEContext *ctx) init_filter(ctx, ctx->filters[i], ctx->filterbuf[i], ape_filter_orders[ctx->fset][i]); } + return 0; } static void ape_unpack_mono(APEContext *ctx, int count) @@ -825,7 +833,14 @@ static int ape_decode_frame(AVCodecContext *avctx, if(!s->samples){ uint32_t offset; - void *tmp_data = av_realloc(s->data, (buf_size + 3) & ~3); + void *tmp_data; + + if (buf_size < 8) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } + + tmp_data = av_realloc(s->data, (buf_size + 3) & ~3); if (!tmp_data) return AVERROR(ENOMEM); s->data = tmp_data; @@ -840,6 +855,10 @@ static int ape_decode_frame(AVCodecContext *avctx, s->data = NULL; return AVERROR_INVALIDDATA; } + if (s->data_end - s->ptr < offset) { + av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); + return AVERROR_INVALIDDATA; + } s->ptr += offset; if (!nblocks || nblocks > INT_MAX) { @@ -852,7 +871,10 @@ static int ape_decode_frame(AVCodecContext *avctx, memset(s->decoded1, 0, sizeof(s->decoded1)); /* Initialize the frame decoder */ - init_frame_decoder(s); + if (init_frame_decoder(s) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error reading frame header\n"); + return AVERROR_INVALIDDATA; + } } if (!s->data) { |