From 203963c2ec316a080f4f8690033d7584fcc37e84 Mon Sep 17 00:00:00 2001 From: Torsten Jager Date: Thu, 12 Jun 2014 15:31:45 +0200 Subject: ff_video_decoder: fix multithreading #5. Avoid rv30/rv40 heap corruption after reading bitstream from invalid location. BTW. Should ff better be more robust there as well? --- src/combined/ffmpeg/ff_video_decoder.c | 43 ++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index 19fe681a1..6c0918007 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -117,7 +117,9 @@ struct ff_video_decoder_s { int size; int skipframes; + int *slice_offset_table; int slice_offset_size; + int slice_offset_pos; AVFrame *av_frame; AVCodecContext *context; @@ -1399,9 +1401,6 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu #ifdef AVCODEC_HAS_SUB_ID this->context->sub_id = _X_BE_32(&this->buf[30]); #endif - this->context->slice_offset = calloc(SLICE_OFFSET_SIZE, sizeof(int)); - this->slice_offset_size = SLICE_OFFSET_SIZE; - this->context->extradata_size = this->size - 26; if (this->context->extradata_size < 8) { this->context->extradata_size= 8; @@ -1492,22 +1491,32 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b #endif } else if (buf->decoder_info[1] == BUF_SPECIAL_RV_CHUNK_TABLE) { - int i; + /* o dear. Multiple decoding threads use individual contexts. + av_decode_video2 () does only copy the _pointer_ to the offsets, + not the offsets themselves. So we must not overwrite anything + that another thread has not yet read. */ + int i, l, total; lprintf("BUF_SPECIAL_RV_CHUNK_TABLE\n"); - this->context->slice_count = buf->decoder_info[2]+1; - - lprintf("slice_count=%d\n", this->context->slice_count); - - if(this->context->slice_count > this->slice_offset_size) { - this->context->slice_offset = realloc(this->context->slice_offset, - sizeof(int)*this->context->slice_count); - this->slice_offset_size = this->context->slice_count; + l = buf->decoder_info[2] + 1; + + total = l * this->class->thread_count; + if (total < SLICE_OFFSET_SIZE) + total = SLICE_OFFSET_SIZE; + if (total > this->slice_offset_size) { + this->slice_offset_table = realloc (this->slice_offset_table, total * sizeof (int)); + this->slice_offset_size = total; } - for(i = 0; i < this->context->slice_count; i++) { - this->context->slice_offset[i] = - ((uint32_t *) buf->decoder_info_ptr[2])[(2*i)+1]; + if (this->slice_offset_pos + l > this->slice_offset_size) + this->slice_offset_pos = 0; + this->context->slice_offset = this->slice_offset_table + this->slice_offset_pos; + this->context->slice_count = l; + + lprintf ("slice_count=%d\n", l); + for (i = 0; i < l; i++) { + this->slice_offset_table[this->slice_offset_pos++] = + ((uint32_t *)buf->decoder_info_ptr[2])[(2 * i) + 1]; lprintf("slice_offset[%d]=%d\n", i, this->context->slice_offset[i]); } } @@ -2458,8 +2467,8 @@ static void ff_dispose (video_decoder_t *this_gen) { this->decoder_ok = 0; } - if(this->context && this->context->slice_offset) - free(this->context->slice_offset); + if (this->slice_offset_table) + free (this->slice_offset_table); if(this->context && this->context->extradata) free(this->context->extradata); -- cgit v1.2.3