Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 9c661e952fbcbf044709f9a7031c68cc4860336b)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -133,7 +133,9 @@ typedef struct FourXContext{ |
133 | 133 |
GetBitContext pre_gb; ///< ac/dc prefix |
134 | 134 |
GetBitContext gb; |
135 | 135 |
const uint8_t *bytestream; |
136 |
+ const uint8_t *bytestream_end; |
|
136 | 137 |
const uint16_t *wordstream; |
138 |
+ const uint16_t *wordstream_end; |
|
137 | 139 |
int mv[256]; |
138 | 140 |
VLC pre_vlc; |
139 | 141 |
int last_dc; |
... | ... |
@@ -308,6 +310,8 @@ static void decode_p_block(FourXContext *f, uint16_t *dst, uint16_t *src, int lo |
308 | 308 |
assert(code>=0 && code<=6); |
309 | 309 |
|
310 | 310 |
if(code == 0){ |
311 |
+ if (f->bytestream_end - f->bytestream < 1) |
|
312 |
+ return; |
|
311 | 313 |
src += f->mv[ *f->bytestream++ ]; |
312 | 314 |
if(start > src || src > end){ |
313 | 315 |
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 |
325 | 325 |
}else if(code == 3 && f->version<2){ |
326 | 326 |
mcdc(dst, src, log2w, h, stride, 1, 0); |
327 | 327 |
}else if(code == 4){ |
328 |
+ if (f->bytestream_end - f->bytestream < 1) |
|
329 |
+ return; |
|
328 | 330 |
src += f->mv[ *f->bytestream++ ]; |
329 | 331 |
if(start > src || src > end){ |
330 | 332 |
av_log(f->avctx, AV_LOG_ERROR, "mv out of pic\n"); |
331 | 333 |
return; |
332 | 334 |
} |
335 |
+ if (f->wordstream_end - f->wordstream < 1) |
|
336 |
+ return; |
|
333 | 337 |
mcdc(dst, src, log2w, h, stride, 1, le2me_16(*f->wordstream++)); |
334 | 338 |
}else if(code == 5){ |
339 |
+ if (f->wordstream_end - f->wordstream < 1) |
|
340 |
+ return; |
|
335 | 341 |
mcdc(dst, src, log2w, h, stride, 0, le2me_16(*f->wordstream++)); |
336 | 342 |
}else if(code == 6){ |
343 |
+ if (f->wordstream_end - f->wordstream < 2) |
|
344 |
+ return; |
|
337 | 345 |
if(log2w){ |
338 | 346 |
dst[0] = le2me_16(*f->wordstream++); |
339 | 347 |
dst[1] = le2me_16(*f->wordstream++); |
... | ... |
@@ -355,6 +367,8 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ |
355 | 355 |
|
356 | 356 |
if(f->version>1){ |
357 | 357 |
extra=20; |
358 |
+ if (length < extra) |
|
359 |
+ return -1; |
|
358 | 360 |
bitstream_size= AV_RL32(buf+8); |
359 | 361 |
wordstream_size= AV_RL32(buf+12); |
360 | 362 |
bytestream_size= AV_RL32(buf+16); |
... | ... |
@@ -365,11 +379,10 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ |
365 | 365 |
bytestream_size= FFMAX(length - bitstream_size - wordstream_size, 0); |
366 | 366 |
} |
367 | 367 |
|
368 |
- if(bitstream_size+ bytestream_size+ wordstream_size + extra != length |
|
369 |
- || bitstream_size > (1<<26) |
|
370 |
- || bytestream_size > (1<<26) |
|
371 |
- || wordstream_size > (1<<26) |
|
372 |
- ){ |
|
368 |
+ if (bitstream_size > length || |
|
369 |
+ bytestream_size > length - bitstream_size || |
|
370 |
+ wordstream_size > length - bytestream_size - bitstream_size || |
|
371 |
+ extra > length - bytestream_size - bitstream_size - wordstream_size){ |
|
373 | 372 |
av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size, |
374 | 373 |
bitstream_size+ bytestream_size+ wordstream_size - length); |
375 | 374 |
return -1; |
... | ... |
@@ -380,7 +393,9 @@ static int decode_p_frame(FourXContext *f, const uint8_t *buf, int length){ |
380 | 380 |
init_get_bits(&f->gb, f->bitstream_buffer, 8*bitstream_size); |
381 | 381 |
|
382 | 382 |
f->wordstream= (const uint16_t*)(buf + extra + bitstream_size); |
383 |
+ f->wordstream_end= f->wordstream + wordstream_size/2; |
|
383 | 384 |
f->bytestream= buf + extra + bitstream_size + wordstream_size; |
385 |
+ f->bytestream_end = f->bytestream + bytestream_size; |
|
384 | 386 |
|
385 | 387 |
init_mv(f); |
386 | 388 |
|
... | ... |
@@ -509,7 +524,7 @@ static int decode_i_mb(FourXContext *f){ |
509 | 509 |
return 0; |
510 | 510 |
} |
511 | 511 |
|
512 |
-static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const buf){ |
|
512 |
+static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const buf, int buf_size){ |
|
513 | 513 |
int frequency[512]; |
514 | 514 |
uint8_t flag[512]; |
515 | 515 |
int up[512]; |
... | ... |
@@ -517,6 +532,7 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const |
517 | 517 |
int bits_tab[257]; |
518 | 518 |
int start, end; |
519 | 519 |
const uint8_t *ptr= buf; |
520 |
+ const uint8_t *ptr_end = buf + buf_size; |
|
520 | 521 |
int j; |
521 | 522 |
|
522 | 523 |
memset(frequency, 0, sizeof(frequency)); |
... | ... |
@@ -527,6 +543,8 @@ static const uint8_t *read_huffman_tables(FourXContext *f, const uint8_t * const |
527 | 527 |
for(;;){ |
528 | 528 |
int i; |
529 | 529 |
|
530 |
+ if (start <= end && ptr_end - ptr < end - start + 1 + 1) |
|
531 |
+ return NULL; |
|
530 | 532 |
for(i=start; i<=end; i++){ |
531 | 533 |
frequency[i]= *ptr++; |
532 | 534 |
} |
... | ... |
@@ -599,10 +617,13 @@ static int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length){ |
599 | 599 |
const int height= f->avctx->height; |
600 | 600 |
uint16_t *dst= (uint16_t*)f->current_picture.data[0]; |
601 | 601 |
const int stride= f->current_picture.linesize[0]>>1; |
602 |
+ const uint8_t *buf_end = buf + length; |
|
602 | 603 |
|
603 | 604 |
for(y=0; y<height; y+=16){ |
604 | 605 |
for(x=0; x<width; x+=16){ |
605 | 606 |
unsigned int color[4], bits; |
607 |
+ if (buf_end - buf < 8) |
|
608 |
+ return -1; |
|
606 | 609 |
memset(color, 0, sizeof(color)); |
607 | 610 |
//warning following is purely guessed ... |
608 | 611 |
color[0]= bytestream_get_le16(&buf); |
... | ... |
@@ -636,18 +657,23 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length){ |
636 | 636 |
uint16_t *dst= (uint16_t*)f->current_picture.data[0]; |
637 | 637 |
const int stride= f->current_picture.linesize[0]>>1; |
638 | 638 |
const unsigned int bitstream_size= AV_RL32(buf); |
639 |
- const int token_count av_unused = AV_RL32(buf + bitstream_size + 8); |
|
640 |
- unsigned int prestream_size= 4*AV_RL32(buf + bitstream_size + 4); |
|
641 |
- const uint8_t *prestream= buf + bitstream_size + 12; |
|
639 |
+ unsigned int prestream_size; |
|
640 |
+ const uint8_t *prestream; |
|
641 |
+ |
|
642 |
+ if (bitstream_size > (1<<26) || length < bitstream_size + 12) |
|
643 |
+ return -1; |
|
644 |
+ prestream_size = 4*AV_RL32(buf + bitstream_size + 4); |
|
645 |
+ prestream = buf + bitstream_size + 12; |
|
642 | 646 |
|
643 |
- if(prestream_size + bitstream_size + 12 != length |
|
644 |
- || bitstream_size > (1<<26) |
|
645 |
- || prestream_size > (1<<26)){ |
|
647 |
+ if (prestream_size > (1<<26) || |
|
648 |
+ prestream_size != length - (bitstream_size + 12)){ |
|
646 | 649 |
av_log(f->avctx, AV_LOG_ERROR, "size mismatch %d %d %d\n", prestream_size, bitstream_size, length); |
647 | 650 |
return -1; |
648 | 651 |
} |
649 | 652 |
|
650 |
- prestream= read_huffman_tables(f, prestream); |
|
653 |
+ prestream= read_huffman_tables(f, prestream, buf + length - prestream); |
|
654 |
+ if (!prestream) |
|
655 |
+ return -1; |
|
651 | 656 |
|
652 | 657 |
init_get_bits(&f->gb, buf + 4, 8*bitstream_size); |
653 | 658 |
|
... | ... |
@@ -684,6 +710,8 @@ static int decode_frame(AVCodecContext *avctx, |
684 | 684 |
AVFrame *p, temp; |
685 | 685 |
int i, frame_4cc, frame_size; |
686 | 686 |
|
687 |
+ if (buf_size < 12) |
|
688 |
+ return AVERROR_INVALIDDATA; |
|
687 | 689 |
frame_4cc= AV_RL32(buf); |
688 | 690 |
if(buf_size != AV_RL32(buf+4)+8 || buf_size < 20){ |
689 | 691 |
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, |
696 | 696 |
const int whole_size= AV_RL32(buf+16); |
697 | 697 |
CFrameBuffer *cfrm; |
698 | 698 |
|
699 |
+ if (data_size < 0 || whole_size < 0) |
|
700 |
+ return AVERROR_INVALIDDATA; |
|
701 |
+ |
|
699 | 702 |
for(i=0; i<CFRAME_BUFFER_COUNT; i++){ |
700 | 703 |
if(f->cfrm[i].id && f->cfrm[i].id < avctx->frame_number) |
701 | 704 |
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, |
712 | 712 |
} |
713 | 713 |
cfrm= &f->cfrm[i]; |
714 | 714 |
|
715 |
+ if (data_size > UINT_MAX - cfrm->size - FF_INPUT_BUFFER_PADDING_SIZE) |
|
716 |
+ return AVERROR_INVALIDDATA; |
|
715 | 717 |
cfrm->data= av_fast_realloc(cfrm->data, &cfrm->allocated_size, cfrm->size + data_size + FF_INPUT_BUFFER_PADDING_SIZE); |
716 | 718 |
if(!cfrm->data){ //explicit check needed as memcpy below might not catch a NULL |
717 | 719 |
av_log(f->avctx, AV_LOG_ERROR, "realloc falure"); |