X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fdsicinav.c;h=cbf7c4a6f821cfa803a674ce4d7c2184633f3748;hb=ea2bb12e3e47baa0f8d50ef68be678f425c7e4cf;hp=0e0d73b68df131de49d6f5d7729e726b9eafc562;hpb=ec6402b7c595c3ceed6d1b8c1b75c6aa8336e052;p=ffmpeg diff --git a/libavcodec/dsicinav.c b/libavcodec/dsicinav.c index 0e0d73b68df..cbf7c4a6f82 100644 --- a/libavcodec/dsicinav.c +++ b/libavcodec/dsicinav.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "mathops.h" typedef enum CinVideoBitmapIndex { @@ -43,7 +44,6 @@ typedef struct CinVideoContext { } CinVideoContext; typedef struct CinAudioContext { - AVCodecContext *avctx; int initial_decode_frame; int delta; } CinAudioContext; @@ -216,7 +216,11 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, bitmap_frame_size = buf_size - 4; /* handle palette */ + if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0))) + return AVERROR_INVALIDDATA; if (palette_type == 0) { + if (palette_colors_count > 256) + return AVERROR_INVALIDDATA; for (i = 0; i < palette_colors_count; ++i) { cin->palette[i] = bytestream_get_le24(&buf); bitmap_frame_size -= 3; @@ -304,7 +308,11 @@ static av_cold int cinaudio_decode_init(AVCodecContext *avctx) { CinAudioContext *cin = avctx->priv_data; - cin->avctx = avctx; + if (avctx->channels != 1) { + av_log_ask_for_sample(avctx, "Number of channels is not supported\n"); + return AVERROR_PATCHWELCOME; + } + cin->initial_decode_frame = 1; cin->delta = 0; avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -317,29 +325,35 @@ static int cinaudio_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; CinAudioContext *cin = avctx->priv_data; - const uint8_t *src = buf; - int16_t *samples = (int16_t *)data; - - buf_size = FFMIN(buf_size, *data_size/2); + const uint8_t *buf_end = buf + avpkt->size; + int16_t *samples = data; + int delta, out_size; + + out_size = (avpkt->size - cin->initial_decode_frame) * + av_get_bytes_per_sample(avctx->sample_fmt); + if (*data_size < out_size) { + av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n"); + return AVERROR(EINVAL); + } + delta = cin->delta; if (cin->initial_decode_frame) { cin->initial_decode_frame = 0; - cin->delta = (int16_t)AV_RL16(src); src += 2; - *samples++ = cin->delta; - buf_size -= 2; + delta = sign_extend(AV_RL16(buf), 16); + buf += 2; + *samples++ = delta; } - while (buf_size > 0) { - cin->delta += cinaudio_delta16_table[*src++]; - cin->delta = av_clip_int16(cin->delta); - *samples++ = cin->delta; - --buf_size; + while (buf < buf_end) { + delta += cinaudio_delta16_table[*buf++]; + delta = av_clip_int16(delta); + *samples++ = delta; } + cin->delta = delta; - *data_size = (uint8_t *)samples - (uint8_t *)data; + *data_size = out_size; - return src - buf; + return avpkt->size; }