Commit dbfd268d authored by Laurent Aimar's avatar Laurent Aimar

Fixed a buffer overread with broken oggs and check alloc values.

parent d4887e00
...@@ -212,6 +212,8 @@ static int Open( vlc_object_t * p_this ) ...@@ -212,6 +212,8 @@ static int Open( vlc_object_t * p_this )
p_demux->pf_demux = Demux; p_demux->pf_demux = Demux;
p_demux->pf_control = Control; p_demux->pf_control = Control;
p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
if( !p_sys )
return VLC_ENOMEM;
memset( p_sys, 0, sizeof( demux_sys_t ) ); memset( p_sys, 0, sizeof( demux_sys_t ) );
p_sys->i_bitrate = 0; p_sys->i_bitrate = 0;
...@@ -549,7 +551,7 @@ static void Ogg_DecodePacket( demux_t *p_demux, ...@@ -549,7 +551,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
if( p_stream->b_force_backup ) if( p_stream->b_force_backup )
{ {
uint8_t *p_extra; uint8_t *p_sav;
bool b_store_size = true; bool b_store_size = true;
bool b_store_num_headers = false; bool b_store_num_headers = false;
...@@ -593,35 +595,48 @@ static void Ogg_DecodePacket( demux_t *p_demux, ...@@ -593,35 +595,48 @@ static void Ogg_DecodePacket( demux_t *p_demux,
/* Backup the ogg packet (likely an header packet) */ /* Backup the ogg packet (likely an header packet) */
p_stream->p_headers = p_stream->p_headers =
realloc( p_stream->p_headers, p_stream->i_headers + realloc( p_sav = p_stream->p_headers, p_stream->i_headers +
p_oggpacket->bytes + (b_store_size ? 2 : 0) + (b_store_num_headers ? 1 : 0) ); p_oggpacket->bytes + (b_store_size ? 2 : 0) + (b_store_num_headers ? 1 : 0) );
p_extra = p_stream->p_headers + p_stream->i_headers; if( p_stream->p_headers )
if( b_store_num_headers )
{ {
/* Kate streams store the number of headers in the first header, uint8_t *p_extra = p_stream->p_headers + p_stream->i_headers;
so we can't just test for 3 as Vorbis/Theora */
*(p_extra++) = p_stream->i_kate_num_headers; if( b_store_num_headers )
} {
if( b_store_size ) /* Kate streams store the number of headers in the first header,
{ so we can't just test for 3 as Vorbis/Theora */
*(p_extra++) = p_oggpacket->bytes >> 8; *(p_extra++) = p_stream->i_kate_num_headers;
*(p_extra++) = p_oggpacket->bytes & 0xFF; }
} if( b_store_size )
memcpy( p_extra, p_oggpacket->packet, p_oggpacket->bytes ); {
p_stream->i_headers += p_oggpacket->bytes + (b_store_size ? 2 : 0) + (b_store_num_headers ? 1 : 0); *(p_extra++) = p_oggpacket->bytes >> 8;
*(p_extra++) = p_oggpacket->bytes & 0xFF;
}
memcpy( p_extra, p_oggpacket->packet, p_oggpacket->bytes );
p_stream->i_headers += p_oggpacket->bytes + (b_store_size ? 2 : 0) + (b_store_num_headers ? 1 : 0);
if( !p_stream->b_force_backup )
{
/* Last header received, commit changes */
free( p_stream->fmt.p_extra );
p_stream->fmt.i_extra = p_stream->i_headers;
p_stream->fmt.p_extra =
realloc( p_stream->fmt.p_extra, p_stream->i_headers );
if( p_stream->fmt.p_extra )
memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
p_stream->i_headers );
else
p_stream->fmt.i_extra = 0;
if( !p_stream->b_force_backup ) if( Ogg_LogicalStreamResetEsFormat( p_demux, p_stream ) )
es_out_Control( p_demux->out, ES_OUT_SET_FMT,
p_stream->p_es, &p_stream->fmt );
}
}
else
{ {
/* Last header received, commit changes */ p_stream->p_headers = p_sav;
p_stream->fmt.i_extra = p_stream->i_headers;
p_stream->fmt.p_extra =
realloc( p_stream->fmt.p_extra, p_stream->i_headers );
memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
p_stream->i_headers );
if( Ogg_LogicalStreamResetEsFormat( p_demux, p_stream ) )
es_out_Control( p_demux->out, ES_OUT_SET_FMT,
p_stream->p_es, &p_stream->fmt );
} }
b_selected = false; /* Discard the header packet */ b_selected = false; /* Discard the header packet */
...@@ -812,12 +827,22 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -812,12 +827,22 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
* We found the beginning of our first logical stream. */ * We found the beginning of our first logical stream. */
while( ogg_page_bos( &oggpage ) ) while( ogg_page_bos( &oggpage ) )
{ {
logical_stream_t **pp_sav = p_ogg->pp_stream;
p_ogg->i_streams++; p_ogg->i_streams++;
p_ogg->pp_stream = p_ogg->pp_stream =
realloc( p_ogg->pp_stream, p_ogg->i_streams * realloc( p_ogg->pp_stream, p_ogg->i_streams *
sizeof(logical_stream_t *) ); sizeof(logical_stream_t *) );
if( !p_ogg->pp_stream )
{
p_ogg->pp_stream = pp_sav;
p_ogg->i_streams--;
return VLC_ENOMEM;
}
p_stream = malloc( sizeof(logical_stream_t) ); p_stream = malloc( sizeof(logical_stream_t) );
if( !p_stream )
return VLC_ENOMEM;
memset( p_stream, 0, sizeof(logical_stream_t) ); memset( p_stream, 0, sizeof(logical_stream_t) );
p_stream->p_headers = 0; p_stream->p_headers = 0;
p_stream->secondary_header_packets = 0; p_stream->secondary_header_packets = 0;
...@@ -1004,12 +1029,15 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -1004,12 +1029,15 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_cat = AUDIO_ES;
i_extra_size = GetWLE((oggpacket.packet+140)); i_extra_size = GetWLE((oggpacket.packet+140));
if( i_extra_size ) if( i_extra_size > 0 && i_extra_size < oggpacket.bytes - 142 )
{ {
p_stream->fmt.i_extra = i_extra_size; p_stream->fmt.i_extra = i_extra_size;
p_stream->fmt.p_extra = malloc( i_extra_size ); p_stream->fmt.p_extra = malloc( i_extra_size );
memcpy( p_stream->fmt.p_extra, if( p_stream->fmt.p_extra )
oggpacket.packet + 142, i_extra_size ); memcpy( p_stream->fmt.p_extra,
oggpacket.packet + 142, i_extra_size );
else
p_stream->fmt.i_extra = 0;
} }
i_format_tag = GetWLE((oggpacket.packet+124)); i_format_tag = GetWLE((oggpacket.packet+124));
...@@ -1104,14 +1132,16 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) ...@@ -1104,14 +1132,16 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
/* We need to get rid of the header packet */ /* We need to get rid of the header packet */
ogg_stream_packetout( &p_stream->os, &oggpacket ); ogg_stream_packetout( &p_stream->os, &oggpacket );
p_stream->fmt.i_extra = GetQWLE(&st->size) - p_stream->fmt.i_extra = GetQWLE(&st->size) - sizeof(stream_header);
sizeof(stream_header); if( p_stream->fmt.i_extra > 0 &&
if( p_stream->fmt.i_extra ) p_stream->fmt.i_extra < oggpacket.bytes - 1 - sizeof(stream_header) )
{ {
p_stream->fmt.p_extra = p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra );
malloc( p_stream->fmt.i_extra ); if( p_stream->fmt.p_extra )
memcpy( p_stream->fmt.p_extra, st + 1, memcpy( p_stream->fmt.p_extra, st + 1,
p_stream->fmt.i_extra ); p_stream->fmt.i_extra );
else
p_stream->fmt.i_extra = 0;
} }
memcpy( p_buffer, st->subtype, 4 ); memcpy( p_buffer, st->subtype, 4 );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment