diff options
author | Anton Khirnov <anton@khirnov.net> | 2014-08-03 10:14:48 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2014-08-06 18:59:27 +0000 |
commit | 7b588bb691644e1b3c168b99accf74248a24e3cf (patch) | |
tree | 496d8b8c8705a81f2deab6ae6b23287f04f7e94b | |
parent | c7d9b473e28238d4a4ef1b7e8b42c1cca256da36 (diff) | |
download | ffmpeg-7b588bb691644e1b3c168b99accf74248a24e3cf.tar.gz |
svq1: do not modify the input packet
The input data must remain constant, make a copy instead. This is in
theory a performance hit, but since I failed to find any samples
using this feature, this should not matter in practice.
Also, check the size of the header, avoiding invalid reads on truncated
data.
CC:libav-stable@libav.org
-rw-r--r-- | libavcodec/svq1dec.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c index 000487b197..14ff41cc18 100644 --- a/libavcodec/svq1dec.c +++ b/libavcodec/svq1dec.c @@ -60,6 +60,10 @@ typedef struct SVQ1Context { HpelDSPContext hdsp; GetBitContext gb; AVFrame *prev; + + uint8_t *pkt_swapped; + int pkt_swapped_allocated; + int width; int height; int frame_code; @@ -626,7 +630,24 @@ static int svq1_decode_frame(AVCodecContext *avctx, void *data, /* swap some header bytes (why?) */ if (s->frame_code != 0x20) { - uint32_t *src = (uint32_t *)(buf + 4); + uint32_t *src; + + if (buf_size < 9 * 4) { + av_log(avctx, AV_LOG_ERROR, "Input packet too small\n"); + return AVERROR_INVALIDDATA; + } + + av_fast_malloc(s->pkt_swapped, &s->pkt_swapped_allocated, + buf_size); + if (!s->pkt_swapped) + return AVERROR(ENOMEM); + + memcpy(s->pkt_swapped, buf, buf_size); + buf = s->pkt_swapped; + init_get_bits(&s->gb, buf, buf_size * 8); + skip_bits(&s->gb, 22); + + src = (uint32_t *)(s->pkt_swapped + 4); for (i = 0; i < 4; i++) src[i] = ((src[i] << 16) | (src[i] >> 16)) ^ src[7 - i]; @@ -796,6 +817,7 @@ static av_cold int svq1_decode_end(AVCodecContext *avctx) SVQ1Context *s = avctx->priv_data; av_frame_free(&s->prev); + av_freep(&s->pkt_swapped); return 0; } |