@ -1591,10 +1591,13 @@ int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecConte
return ff_mpeg_update_thread_context ( dst , src ) ;
}
static int get_slice_offset ( AVCodecContext * avctx , const uint8_t * buf , int n )
static int get_slice_offset ( AVCodecContext * avctx , const uint8_t * buf , int n , int slice_count , int buf_size )
{
if ( avctx - > slice_count ) return avctx - > slice_offset [ n ] ;
else return AV_RL32 ( buf + n * 8 - 4 ) = = 1 ? AV_RL32 ( buf + n * 8 ) : AV_RB32 ( buf + n * 8 ) ;
if ( n < slice_count ) {
if ( avctx - > slice_count ) return avctx - > slice_offset [ n ] ;
else return AV_RL32 ( buf + n * 8 - 4 ) = = 1 ? AV_RL32 ( buf + n * 8 ) : AV_RB32 ( buf + n * 8 ) ;
} else
return buf_size ;
}
static int finish_frame ( AVCodecContext * avctx , AVFrame * pict )
@ -1652,6 +1655,7 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
const uint8_t * slices_hdr = NULL ;
int last = 0 ;
int faulty_b = 0 ;
int offset ;
/* no supplementary picture */
if ( buf_size = = 0 ) {
@ -1674,13 +1678,13 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
} else
slice_count = avctx - > slice_count ;
offset = get_slice_offset ( avctx , slices_hdr , 0 , slice_count , buf_size ) ;
//parse first slice header to check whether this frame can be decoded
if ( get_slice_offset ( avctx , slices_hdr , 0 ) < 0 | |
get_slice_offset ( avctx , slices_hdr , 0 ) > buf_size ) {
if ( offset < 0 | | offset > buf_size ) {
av_log ( avctx , AV_LOG_ERROR , " Slice offset is invalid \n " ) ;
return AVERROR_INVALIDDATA ;
}
init_get_bits ( & s - > gb , buf + get_slice_ offset( avctx , slices_hdr , 0 ) , ( buf_size - get_slice_ offset( avctx , slices_hdr , 0 ) ) * 8 ) ;
init_get_bits ( & s - > gb , buf + offset , ( buf_size - offset ) * 8 ) ;
if ( r - > parse_slice_header ( r , & r - > s . gb , & si ) < 0 | | si . start ) {
av_log ( avctx , AV_LOG_ERROR , " First slice header is incorrect \n " ) ;
return AVERROR_INVALIDDATA ;
@ -1783,40 +1787,32 @@ int ff_rv34_decode_frame(AVCodecContext *avctx,
return AVERROR_INVALIDDATA ;
for ( i = 0 ; i < slice_count ; i + + ) {
int offset = get_slice_offset ( avctx , slices_hdr , i ) ;
int offset = get_slice_offset ( avctx , slices_hdr , i , slice_count , buf_size ) ;
int offset1 = get_slice_offset ( avctx , slices_hdr , i + 1 , slice_count , buf_size ) ;
int size ;
if ( i + 1 = = slice_count )
size = buf_size - offset ;
else
size = get_slice_offset ( avctx , slices_hdr , i + 1 ) - offset ;
if ( offset < 0 | | offset > buf_size ) {
if ( offset < 0 | | offset > offset1 | | offset1 > buf_size ) {
av_log ( avctx , AV_LOG_ERROR , " Slice offset is invalid \n " ) ;
break ;
}
size = offset1 - offset ;
r - > si . end = s - > mb_width * s - > mb_height ;
s - > mb_num_left = r - > s . mb_x + r - > s . mb_y * r - > s . mb_width - r - > si . start ;
if ( i + 1 < slice_count ) {
if ( get_slice_offset ( avctx , slices_hdr , i + 1 ) < 0 | |
get_slice_offset ( avctx , slices_hdr , i + 1 ) > buf_size ) {
int offset2 = get_slice_offset ( avctx , slices_hdr , i + 2 , slice_count , buf_size ) ;
if ( offset2 < offset1 | | offset2 > buf_size ) {
av_log ( avctx , AV_LOG_ERROR , " Slice offset is invalid \n " ) ;
break ;
}
init_get_bits ( & s - > gb , buf + get_slice_ offset( avctx , slices_hdr , i + 1 ) , ( buf_size - get_slice_ offset( avctx , slices_hdr , i + 1 ) ) * 8 ) ;
init_get_bits ( & s - > gb , buf + offset1 , ( buf_size - offset1 ) * 8 ) ;
if ( r - > parse_slice_header ( r , & r - > s . gb , & si ) < 0 ) {
if ( i + 2 < slice_count )
size = get_slice_offset ( avctx , slices_hdr , i + 2 ) - offset ;
else
size = buf_size - offset ;
size = offset2 - offset ;
} else
r - > si . end = si . start ;
}
if ( size < 0 | | size > buf_size - offset ) {
av_log ( avctx , AV_LOG_ERROR , " Slice size is invalid \n " ) ;
break ;
}
av_assert0 ( size > = 0 & & size < = buf_size - offset ) ;
last = rv34_decode_slice ( r , r - > si . end , buf + offset , size ) ;
if ( last )
break ;