Commit 9c661e95 authored by Laurent Aimar's avatar Laurent Aimar Committed by Michael Niedermayer

Check for out of bound accesses in the 4xm decoder.

Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent b399cbfb
...@@ -133,7 +133,9 @@ typedef struct FourXContext{ ...@@ -133,7 +133,9 @@ typedef struct FourXContext{
GetBitContext pre_gb; ///< ac/dc prefix GetBitContext pre_gb; ///< ac/dc prefix
GetBitContext gb; GetBitContext gb;
const uint8_t *bytestream; const uint8_t *bytestream;
const uint8_t *bytestream_end;
const uint16_t *wordstream; const uint16_t *wordstream;
const uint16_t *wordstream_end;
int mv[256]; int mv[256];
VLC pre_vlc; VLC pre_vlc;
int last_dc; int last_dc;
...@@ -328,6 +330,8 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo ...@@ -328,6 +330,8 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo
assert(code>=0 && code<=6); assert(code>=0 && code<=6);
if(code == 0){ if(code == 0){
if (f->bytestream_end - f->bytestream < 1)
return;
src += f->mv[ *f->bytestream++ ]; src += f->mv[ *f->bytestream++ ];
if(start > src || src > end){ if(start > src || src > end){
av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
...@@ -345,15 +349,23 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo ...@@ -345,15 +349,23 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo
}else if(code == 3 && f->version<2){ }else if(code == 3 && f->version<2){
mcdc(dst, src, log2w, h, stride, 1, 0); mcdc(dst, src, log2w, h, stride, 1, 0);
}else if(code == 4){ }else if(code == 4){
if (f->bytestream_end - f->bytestream < 1)
return;
src += f->mv[ *f->bytestream++ ]; src += f->mv[ *f->bytestream++ ];
if(start > src || src > end){ if(start > src || src > end){
av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n");
return; return;
} }
if (f->wordstream_end - f->wordstream < 1)
return;
mcdc(dst, src, log2w, h, stride, 1, av_le2ne16(*f->wordstream++)); mcdc(dst, src, log2w, h, stride, 1, av_le2ne16(*f->wordstream++));
}else if(code == 5){ }else if(code == 5){
if (f->wordstream_end - f->wordstream < 1)
return;
mcdc(dst, src, log2w, h, stride, 0, av_le2ne16(*f->wordstream++)); mcdc(dst, src, log2w, h, stride, 0, av_le2ne16(*f->wordstream++));
}else if(code == 6){ }else if(code == 6){
if (f->wordstream_end - f->wordstream < 2)
return;
if(log2w){ if(log2w){
dst[0] = av_le2ne16(*f->wordstream++); dst[0] = av_le2ne16(*f->wordstream++);
dst[1] = av_le2ne16(*f->wordstream++); dst[1] = av_le2ne16(*f->wordstream++);
...@@ -375,6 +387,8 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ ...@@ -375,6 +387,8 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){
if(f->version>1){ if(f->version>1){
extra=20; extra=20;
if (length < extra)
return -1;
bitstream_size= AV_RL32(buf+8); bitstream_size= AV_RL32(buf+8);
wordstream_size= AV_RL32(buf+12); wordstream_size= AV_RL32(buf+12);
bytestream_size= AV_RL32(buf+16); bytestream_size= AV_RL32(buf+16);
...@@ -385,11 +399,10 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ ...@@ -385,11 +399,10 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){
bytestream_size= FFMAX(length - bitstream_size - wordstream_size, 0); bytestream_size= FFMAX(length - bitstream_size - wordstream_size, 0);
} }
if(bitstream_size+ bytestream_size+ wordstream_size + extra != length if (bitstream_size > length ||
|| bitstream_size > (1<<26) bytestream_size > length - bitstream_size ||
|| bytestream_size > (1<<26) wordstream_size > length - bytestream_size - bitstream_size ||
|| wordstream_size > (1<<26) 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, 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); bitstream_size+ bytestream_size+ wordstream_size - length);
return -1; return -1;
...@@ -403,7 +416,9 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ ...@@ -403,7 +416,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); init_get_bits(&f->gb, f->bitstream_buffer, 8*bitstream_size);
f->wordstream= (const uint16_t*)(buf + extra + 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= buf + extra + bitstream_size + wordstream_size;
f->bytestream_end = f->bytestream + bytestream_size;
init_mv(f); init_mv(f);
...@@ -532,7 +547,7 @@ static int decode_i_mb(FourXContext *f){ ...@@ -532,7 +547,7 @@ static int decode_i_mb(FourXContext *f){
return 0; 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]; int frequency[512];
uint8_t flag[512]; uint8_t flag[512];
int up[512]; int up[512];
...@@ -540,6 +555,7 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const ...@@ -540,6 +555,7 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const
int bits_tab[257]; int bits_tab[257];
int start, end; int start, end;
const uint8_t *ptr= buf; const uint8_t *ptr= buf;
const uint8_t *ptr_end = buf + buf_size;
int j; int j;
memset(frequency, 0, sizeof(frequency)); memset(frequency, 0, sizeof(frequency));
...@@ -550,6 +566,8 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const ...@@ -550,6 +566,8 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const
for(;;){ for(;;){
int i; int i;
if (start <= end && ptr_end - ptr < end - start + 1 + 1)
return NULL;
for(i=start; i<=end; i++){ for(i=start; i<=end; i++){
frequency[i]= *ptr++; frequency[i]= *ptr++;
} }
...@@ -623,10 +641,13 @@ static int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length){ ...@@ -623,10 +641,13 @@ static int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length){
const int height= f->avctx->height; const int height= f->avctx->height;
uint16_t *dst= (uint16_t*)f->current_picture.data[0]; uint16_t *dst= (uint16_t*)f->current_picture.data[0];
const int stride= f->current_picture.linesize[0]>>1; const int stride= f->current_picture.linesize[0]>>1;
const uint8_t *buf_end = buf + length;
for(y=0; y<height; y+=16){ for(y=0; y<height; y+=16){
for(x=0; x<width; x+=16){ for(x=0; x<width; x+=16){
unsigned int color[4], bits; unsigned int color[4], bits;
if (buf_end - buf < 8)
return -1;
memset(color, 0, sizeof(color)); memset(color, 0, sizeof(color));
//warning following is purely guessed ... //warning following is purely guessed ...
color[0]= bytestream_get_le16(&buf); color[0]= bytestream_get_le16(&buf);
...@@ -660,18 +681,23 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length){ ...@@ -660,18 +681,23 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length){
uint16_t *dst= (uint16_t*)f->current_picture.data[0]; uint16_t *dst= (uint16_t*)f->current_picture.data[0];
const int stride= f->current_picture.linesize[0]>>1; const int stride= f->current_picture.linesize[0]>>1;
const unsigned int bitstream_size= AV_RL32(buf); const unsigned int bitstream_size= AV_RL32(buf);
const int token_count av_unused = AV_RL32(buf + bitstream_size + 8); unsigned int prestream_size;
unsigned int prestream_size= 4*AV_RL32(buf + bitstream_size + 4); const uint8_t *prestream;
const uint8_t *prestream= buf + bitstream_size + 12;
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 if (prestream_size > (1<<26) ||
|| bitstream_size > (1<<26) prestream_size != length - (bitstream_size + 12)){
|| prestream_size > (1<<26)){
av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n", prestream_size, bitstream_size, length); av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n", prestream_size, bitstream_size, length);
return -1; 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); init_get_bits(&f->gb, buf + 4, 8*bitstream_size);
...@@ -713,6 +739,8 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -713,6 +739,8 @@ static int decode_frame(AVCodecContext *avctx,
AVFrame *p, temp; AVFrame *p, temp;
int i, frame_4cc, frame_size; int i, frame_4cc, frame_size;
if (buf_size < 12)
return AVERROR_INVALIDDATA;
frame_4cc= AV_RL32(buf); frame_4cc= AV_RL32(buf);
if(buf_size != AV_RL32(buf+4)+8 || buf_size < 20){ 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)); av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d\n", buf_size, AV_RL32(buf+4));
...@@ -725,6 +753,9 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -725,6 +753,9 @@ static int decode_frame(AVCodecContext *avctx,
const int whole_size= AV_RL32(buf+16); const int whole_size= AV_RL32(buf+16);
CFrameBuffer *cfrm; CFrameBuffer *cfrm;
if (data_size < 0 || whole_size < 0)
return AVERROR_INVALIDDATA;
for(i=0; i<CFRAME_BUFFER_COUNT; i++){ for(i=0; i<CFRAME_BUFFER_COUNT; i++){
if(f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number) 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); av_log(f->avctx, AV_LOG_ERROR, "lost c frame %d\n", f->cfrm[i].id);
...@@ -741,6 +772,8 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -741,6 +772,8 @@ static int decode_frame(AVCodecContext *avctx,
} }
cfrm= &f->cfrm[i]; 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); 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 if(!cfrm->data){ //explicit check needed as memcpy below might not catch a NULL
av_log(f->avctx, AV_LOG_ERROR, "realloc falure"); av_log(f->avctx, AV_LOG_ERROR, "realloc falure");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment