diff options
author | Laurent Aimar <fenrir@videolan.org> | 2011-10-02 00:38:27 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-11-06 19:49:12 +0100 |
commit | 8e6173c76a33ae3358314eace94e3e854c4c2555 (patch) | |
tree | b6ddf299967ef029cd7bacf645be4231ef0c8b51 | |
parent | 1a6f024520d667a9fbf63e701cc029a6d556d76e (diff) | |
download | ffmpeg-8e6173c76a33ae3358314eace94e3e854c4c2555.tar.gz |
Check for out of bound accesses in the 4xm decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 9c661e952fbcbf044709f9a7031c68cc4860336b)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavcodec/4xm.c | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 5c96baaf3f..e33001f306 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -133,7 +133,9 @@ typedef struct FourXContext{ GetBitContext pre_gb; ///< ac/dc prefix GetBitContext gb; const uint8_t *bytestream; + const uint8_t *bytestream_end; const uint16_t *wordstream; + const uint16_t *wordstream_end; int mv[256]; VLC pre_vlc; int last_dc; @@ -308,6 +310,8 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo assert(code>=0 && code<=6); if(code == 0){ + if (f->bytestream_end - f->bytestream < 1) + return; src += f->mv[ *f->bytestream++ ]; if(start > src || src > end){ av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); @@ -325,15 +329,23 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo }else if(code == 3 && f->version<2){ mcdc(dst, src, log2w, h, stride, 1, 0); }else if(code == 4){ + if (f->bytestream_end - f->bytestream < 1) + return; src += f->mv[ *f->bytestream++ ]; if(start > src || src > end){ av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); return; } + if (f->wordstream_end - f->wordstream < 1) + return; mcdc(dst, src, log2w, h, stride, 1, le2me_16(*f->wordstream++)); }else if(code == 5){ + if (f->wordstream_end - f->wordstream < 1) + return; mcdc(dst, src, log2w, h, stride, 0, le2me_16(*f->wordstream++)); }else if(code == 6){ + if (f->wordstream_end - f->wordstream < 2) + return; if(log2w){ dst[0] = le2me_16(*f->wordstream++); dst[1] = le2me_16(*f->wordstream++); @@ -355,6 +367,8 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ if(f->version>1){ extra=20; + if (length < extra) + return -1; bitstream_size= AV_RL32(buf+8); wordstream_size= AV_RL32(buf+12); bytestream_size= AV_RL32(buf+16); @@ -365,11 +379,10 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ bytestream_size= FFMAX(length - bitstream_size - wordstream_size, 0); } - if(bitstream_size+ bytestream_size+ wordstream_size + extra != length - || bitstream_size > (1<<26) - || bytestream_size > (1<<26) - || wordstream_size > (1<<26) - ){ + if (bitstream_size > length || + bytestream_size > length - bitstream_size || + wordstream_size > length - bytestream_size - bitstream_size || + extra > length - bytestream_size - bitstream_size - wordstream_size){ av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size, bitstream_size+ bytestream_size+ wordstream_size - length); return -1; @@ -380,7 +393,9 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ init_get_bits(&f->gb, f->bitstream_buffer, 8*bitstream_size); f->wordstream= (const uint16_t*)(buf + extra + bitstream_size); + f->wordstream_end= f->wordstream + wordstream_size/2; f->bytestream= buf + extra + bitstream_size + wordstream_size; + f->bytestream_end = f->bytestream + bytestream_size; init_mv(f); @@ -509,7 +524,7 @@ static int decode_i_mb(FourXContext *f){ return 0; } -static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const buf){ +static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const buf, int buf_size){ int frequency[512]; uint8_t flag[512]; int up[512]; @@ -517,6 +532,7 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const int bits_tab[257]; int start, end; const uint8_t *ptr= buf; + const uint8_t *ptr_end = buf + buf_size; int j; memset(frequency, 0, sizeof(frequency)); @@ -527,6 +543,8 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const for(;;){ int i; + if (start <= end && ptr_end - ptr < end - start + 1 + 1) + return NULL; for(i=start; i<=end; i++){ frequency[i]= *ptr++; } @@ -599,10 +617,13 @@ static int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length){ const int height= f->avctx->height; uint16_t *dst= (uint16_t*)f->current_picture.data[0]; const int stride= f->current_picture.linesize[0]>>1; + const uint8_t *buf_end = buf + length; for(y=0; y<height; y+=16){ for(x=0; x<width; x+=16){ unsigned int color[4], bits; + if (buf_end - buf < 8) + return -1; memset(color, 0, sizeof(color)); //warning following is purely guessed ... color[0]= bytestream_get_le16(&buf); @@ -636,18 +657,23 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length){ uint16_t *dst= (uint16_t*)f->current_picture.data[0]; const int stride= f->current_picture.linesize[0]>>1; const unsigned int bitstream_size= AV_RL32(buf); - const int token_count av_unused = AV_RL32(buf + bitstream_size + 8); - unsigned int prestream_size= 4*AV_RL32(buf + bitstream_size + 4); - const uint8_t *prestream= buf + bitstream_size + 12; + unsigned int prestream_size; + const uint8_t *prestream; + + if (bitstream_size > (1<<26) || length < bitstream_size + 12) + return -1; + prestream_size = 4*AV_RL32(buf + bitstream_size + 4); + prestream = buf + bitstream_size + 12; - if(prestream_size + bitstream_size + 12 != length - || bitstream_size > (1<<26) - || prestream_size > (1<<26)){ + if (prestream_size > (1<<26) || + prestream_size != length - (bitstream_size + 12)){ av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n", prestream_size, bitstream_size, length); return -1; } - prestream= read_huffman_tables(f, prestream); + prestream= read_huffman_tables(f, prestream, buf + length - prestream); + if (!prestream) + return -1; init_get_bits(&f->gb, buf + 4, 8*bitstream_size); @@ -684,6 +710,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *p, temp; int i, frame_4cc, frame_size; + if (buf_size < 12) + return AVERROR_INVALIDDATA; frame_4cc= AV_RL32(buf); if(buf_size != AV_RL32(buf+4)+8 || buf_size < 20){ av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n", buf_size, AV_RL32(buf+4)); @@ -696,6 +724,9 @@ static int decode_frame(AVCodecContext *avctx, const int whole_size= AV_RL32(buf+16); CFrameBuffer *cfrm; + if (data_size < 0 || whole_size < 0) + return AVERROR_INVALIDDATA; + for(i=0; i<CFRAME_BUFFER_COUNT; i++){ if(f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number) av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n", f->cfrm[i].id); @@ -712,6 +743,8 @@ static int decode_frame(AVCodecContext *avctx, } cfrm= &f->cfrm[i]; + if (data_size > UINT_MAX - cfrm->size - FF_INPUT_BUFFER_PADDING_SIZE) + return AVERROR_INVALIDDATA; cfrm->data= av_fast_realloc(cfrm->data, &cfrm->allocated_size, cfrm->size + data_size + FF_INPUT_BUFFER_PADDING_SIZE); if(!cfrm->data){ //explicit check needed as memcpy below might not catch a NULL av_log(f->avctx, AV_LOG_ERROR, "realloc falure"); |