From 22493ab9cb9f7d6c609e5d6b0c93d874c39b9700 Mon Sep 17 00:00:00 2001 From: Mike Melanson Date: Mon, 19 May 2003 01:22:46 +0000 Subject: fix subtle logic problem in block unpacker that leads to incorrect token decoding which leads to segfaults Originally committed as revision 1890 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/vp3.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 409e7923ad..2039a40a4b 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -1132,6 +1132,7 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) int current_run = 0; int decode_fully_flags = 0; int decode_partial_blocks = 0; + int first_c_fragment_seen; int i, j; int current_fragment; @@ -1223,6 +1224,7 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) s->coded_fragment_list_index = 0; s->first_coded_y_fragment = s->first_coded_c_fragment = 0; s->last_coded_y_fragment = s->last_coded_c_fragment = -1; + first_c_fragment_seen = 0; memset(s->macroblock_coding, MODE_COPY, s->macroblock_count); for (i = 0; i < s->superblock_count; i++) { @@ -1253,15 +1255,18 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) } if (bit) { - /* mode will be decoded in the next phase */ + /* default mode; actual mode will be decoded in + * the next phase */ s->all_fragments[current_fragment].coding_method = MODE_INTER_NO_MV; s->coded_fragment_list[s->coded_fragment_list_index] = current_fragment; if ((current_fragment >= s->u_fragment_start) && - (s->last_coded_y_fragment == -1)) { + (s->last_coded_y_fragment == -1) && + (!first_c_fragment_seen)) { s->first_coded_c_fragment = s->coded_fragment_list_index; s->last_coded_y_fragment = s->first_coded_c_fragment - 1; + first_c_fragment_seen = 1; } s->coded_fragment_list_index++; s->macroblock_coding[s->all_fragments[current_fragment].macroblock] = MODE_INTER_NO_MV; @@ -1286,9 +1291,11 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) s->coded_fragment_list[s->coded_fragment_list_index] = current_fragment; if ((current_fragment >= s->u_fragment_start) && - (s->last_coded_y_fragment == -1)) { + (s->last_coded_y_fragment == -1) && + (!first_c_fragment_seen)) { s->first_coded_c_fragment = s->coded_fragment_list_index; s->last_coded_y_fragment = s->first_coded_c_fragment - 1; + first_c_fragment_seen = 1; } s->coded_fragment_list_index++; s->macroblock_coding[s->all_fragments[current_fragment].macroblock] = MODE_INTER_NO_MV; @@ -1299,11 +1306,13 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb) } } - if (s->first_coded_c_fragment == 0) - /* no C fragments coded */ + if (!first_c_fragment_seen) + /* only Y fragments coded in this frame */ s->last_coded_y_fragment = s->coded_fragment_list_index - 1; - else + else + /* end the list of coded fragments */ s->last_coded_c_fragment = s->coded_fragment_list_index - 1; + debug_block_coding(" %d total coded fragments, y: %d -> %d, c: %d -> %d\n", s->coded_fragment_list_index, s->first_coded_y_fragment, @@ -1656,14 +1665,12 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, DCTELEM coeff; Vp3Fragment *fragment; - if ((first_fragment < 0) || - (first_fragment >= s->fragment_count) || - (last_fragment < 0) || + if ((first_fragment >= s->fragment_count) || (last_fragment >= s->fragment_count)) { printf (" vp3:unpack_vlcs(): bad fragment number (%d -> %d ?)\n", first_fragment, last_fragment); - return 1; + return 0; } for (i = first_fragment; i <= last_fragment; i++) { @@ -2433,6 +2440,11 @@ static int vp3_decode_frame(AVCodecContext *avctx, counter++; if (s->keyframe) { + + debug_vp3(", keyframe\n"); + /* skip the other 2 header bytes for now */ + skip_bits(&gb, 16); + if (s->last_frame.data[0] == s->golden_frame.data[0]) { if (s->golden_frame.data[0]) avctx->release_buffer(avctx, &s->golden_frame); @@ -2458,22 +2470,16 @@ static int vp3_decode_frame(AVCodecContext *avctx, } else { + debug_vp3("\n"); + /* allocate a new current frame */ s->current_frame.reference = 0; if(avctx->get_buffer(avctx, &s->current_frame) < 0) { printf("vp3: get_buffer() failed\n"); return -1; } - } - if (s->keyframe) { - debug_vp3(", keyframe\n"); - /* skip the other 2 header bytes for now */ - skip_bits(&gb, 16); - } else - debug_vp3("\n"); - init_frame(s, &gb); #if KEYFRAMES_ONLY -- cgit v1.2.3