vlc/vlc-2.2 | branch: master | Francois Cartegnie <[email protected]> | Wed Sep 24 12:58:04 2014 +0200| [c0d2943735e0ac59c96dce5a69310f67a6a955db] | committer: Jean-Baptiste Kempf
demux: ogg: fix packet count heap overflow (fix #12265) (cherry picked from commit 5e009c7210154b56212e65299dfd92dd85e55b9e) Signed-off-by: Jean-Baptiste Kempf <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc/vlc-2.2.git/?a=commit;h=c0d2943735e0ac59c96dce5a69310f67a6a955db --- modules/demux/ogg.c | 59 ++++++++++++++++++++++++++++++++++----------------- modules/demux/ogg.h | 8 +++++-- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c index b895ed3..d7cd179 100644 --- a/modules/demux/ogg.c +++ b/modules/demux/ogg.c @@ -423,6 +423,9 @@ static int Demux( demux_t * p_demux ) p_sys->current_page.body_len ) ); + const int i_page_packets = ogg_page_packets( &p_sys->current_page ); + bool b_doprepcr = false; + if ( p_stream->i_pcr < VLC_TS_0 && ogg_page_granulepos( &p_sys->current_page ) > 0 ) { // PASS 0 @@ -431,14 +434,32 @@ static int Demux( demux_t * p_demux ) p_stream->fmt.i_codec == VLC_CODEC_SPEEX || p_stream->fmt.i_cat == VIDEO_ES ) { - assert( p_stream->p_prepcr_blocks == NULL ); - p_stream->i_prepcr_blocks = 0; - p_stream->p_prepcr_blocks = malloc( sizeof(block_t *) * ogg_page_packets( &p_sys->current_page ) ); + assert( p_stream->prepcr.pp_blocks == NULL ); + b_doprepcr = true; } } + int i_real_page_packets = 0; while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) { + i_real_page_packets++; + int i_max_packets = __MAX(i_page_packets, i_real_page_packets); + if ( b_doprepcr && p_stream->prepcr.i_size < i_max_packets ) + { + /* always double alloc for performance */ + i_max_packets = __MAX( i_max_packets << 1, 255 ); + /* alloc or realloc */ + block_t **pp_realloc = realloc( p_stream->prepcr.pp_blocks, + sizeof(block_t *) * i_max_packets ); + if ( !pp_realloc ) + { + /* drop it then */ + continue; + } + p_stream->prepcr.i_size = i_max_packets; + p_stream->prepcr.pp_blocks = pp_realloc; + } + /* Read info from any secondary header packets, if there are any */ if( p_stream->i_secondary_header_packets > 0 ) { @@ -480,10 +501,9 @@ static int Demux( demux_t * p_demux ) } Ogg_DecodePacket( p_demux, p_stream, &oggpacket ); - } - if ( p_stream->p_prepcr_blocks ) + if ( p_stream->prepcr.pp_blocks ) { int64_t pagestamp = Oggseek_GranuleToAbsTimestamp( p_stream, ogg_page_granulepos( &p_sys->current_page ), false ); p_stream->i_previous_pcr = pagestamp; @@ -491,9 +511,9 @@ static int Demux( demux_t * p_demux ) int i_prev_blocksize = 0; #endif // PASS 1 - for( int i=0; i<p_stream->i_prepcr_blocks; i++ ) + for( int i=0; i<p_stream->prepcr.i_used; i++ ) { - block_t *p_block = p_stream->p_prepcr_blocks[i]; + block_t *p_block = p_stream->prepcr.pp_blocks[i]; ogg_packet dumb_packet; dumb_packet.bytes = p_block->i_buffer; dumb_packet.packet = p_block->p_buffer; @@ -532,9 +552,9 @@ static int Demux( demux_t * p_demux ) // PASS 2 bool b_fixed = false; - for( int i=p_stream->i_prepcr_blocks - 1; i>=0; i-- ) + for( int i=p_stream->prepcr.i_used - 1; i>=0; i-- ) { - block_t *p_block = p_stream->p_prepcr_blocks[i]; + block_t *p_block = p_stream->prepcr.pp_blocks[i]; switch( p_stream->fmt.i_codec ) { case VLC_CODEC_SPEEX: @@ -568,8 +588,8 @@ static int Demux( demux_t * p_demux ) p_stream->i_previous_granulepos = ogg_page_granulepos( &p_sys->current_page ); } - FREENULL( p_stream->p_prepcr_blocks ); - p_stream->i_prepcr_blocks = 0; + FREENULL(p_stream->prepcr.pp_blocks); + p_stream->prepcr.i_used = 0; Ogg_SendOrQueueBlocks( p_demux, p_stream, NULL ); @@ -662,8 +682,9 @@ static void Ogg_ResetStream( logical_stream_t *p_stream ) p_stream->i_previous_granulepos = -1; p_stream->i_previous_pcr = VLC_TS_UNKNOWN; ogg_stream_reset( &p_stream->os ); - FREENULL( p_stream->p_prepcr_blocks ); - p_stream->i_prepcr_blocks = 0; + FREENULL( p_stream->prepcr.pp_blocks ); + p_stream->prepcr.i_size = 0; + p_stream->prepcr.i_used = 0; } static void Ogg_ResetStreamsHelper( demux_sys_t *p_sys ) @@ -1050,13 +1071,13 @@ static void Ogg_SendOrQueueBlocks( demux_t *p_demux, logical_stream_t *p_stream, block_t *p_block ) { demux_sys_t *p_ogg = p_demux->p_sys; - if ( !p_stream->p_es || p_stream->p_prepcr_blocks || p_stream->i_pcr == VLC_TS_UNKNOWN ) + if ( !p_stream->p_es || p_stream->prepcr.pp_blocks || p_stream->i_pcr == VLC_TS_UNKNOWN ) { if ( !p_block ) return; - if ( p_stream->p_prepcr_blocks ) + if ( p_stream->prepcr.pp_blocks ) { - assert( p_stream->p_prepcr_blocks ); - p_stream->p_prepcr_blocks[p_stream->i_prepcr_blocks++] = p_block; + assert( p_stream->prepcr.i_size ); + p_stream->prepcr.pp_blocks[p_stream->prepcr.i_used++] = p_block; } DemuxDebug( msg_Dbg( p_demux, "block prepcr append > pts %"PRId64" spcr %"PRId64" pcr %"PRId64, p_block->i_pts, p_stream->i_pcr, p_ogg->i_pcr ); ) @@ -2181,7 +2202,7 @@ static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_strea block_ChainRelease( p_stream->p_preparse_block ); p_stream->p_preparse_block = NULL; } - free( p_stream->p_prepcr_blocks ); + free( p_stream->prepcr.pp_blocks ); free( p_stream ); } @@ -2525,7 +2546,7 @@ static void Ogg_DecodeVorbisHeader( logical_stream_t *p_stream, switch( i_number ) { case VORBIS_HEADER_IDENTIFICATION: - p_stream->special.vorbis.p_info = malloc( sizeof(vorbis_info) ); + p_stream->special.vorbis.p_info = calloc( 1, sizeof(vorbis_info) ); p_stream->special.vorbis.p_comment = malloc( sizeof(vorbis_comment) ); if ( !p_stream->special.vorbis.p_info || !p_stream->special.vorbis.p_comment ) { diff --git a/modules/demux/ogg.h b/modules/demux/ogg.h index ff6fb18..ff6d538 100644 --- a/modules/demux/ogg.h +++ b/modules/demux/ogg.h @@ -115,8 +115,12 @@ typedef struct logical_stream_s int i_secondary_header_packets; /* All blocks which can't be sent because track PCR isn't known yet */ - block_t **p_prepcr_blocks; - int i_prepcr_blocks; + struct + { + block_t **pp_blocks; + uint8_t i_size; /* max 255 */ + uint8_t i_used; + } prepcr; /* All blocks that are queued because ES isn't created yet */ block_t *p_preparse_block; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
