Floating Point Exception (Divide by 0) in AIFF Demuxer
Upon opening an AIFF file, inside Open(), the following fields are read:
135 if( !memcmp( p_peek, "COMM", 4 ) )
136 {
137 if( stream_Peek( p_demux->s, &p_peek, 18+8 ) < 18+8 )
138 goto error;
139
140 es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 't', 'w', 'o', 's' ) );
141 p_sys->fmt.audio.i_channels = GetWBE( &p_peek[8] );
142 p_sys->fmt.audio.i_bitspersample = GetWBE( &p_peek[14] );
143 p_sys->fmt.audio.i_rate = GetF80BE( &p_peek[16] );
144
145 msg_Dbg( p_demux, "COMM: channels=%d samples_frames=%d bits=%d rate=%d",
146 GetWBE( &p_peek[8] ), GetDWBE( &p_peek[10] ), GetWBE( &p_peek[14] ), GetF80BE( &p_peek[16] ) );
147 }
The following function is used to read a floating point into i_rate:
81 /* GetF80BE: read a 80 bits float in big endian */
82 static unsigned int GetF80BE( const uint8_t p[10] )
83 {
84 unsigned int i_mantissa = GetDWBE( &p[2] );
85 int i_exp = 30 - p[1];
86 unsigned int i_last = 0;
87
88 while( i_exp-- > 0 )
89 {
90 i_last = i_mantissa;
91 i_mantissa >>= 1;
92 }
93 if( i_last&0x01 )
94 {
95 i_mantissa++;
96 }
97 return i_mantissa;
98 }
By nulling 6 bytes starting at offset 28 of the file, we can make i_rate = 0. Later, on line 312, i_rate is used as a divisor without checking its validity, resulting in a divide by 0 / floating point exception:
272 static int Control( demux_t *p_demux, int i_query, va_list args )
273 {
274 demux_sys_t *p_sys = p_demux->p_sys;
275 double f, *pf;
276 int64_t *pi64;
277
278 switch( i_query )
279 {
296 case DEMUX_SET_POSITION:
297 {
298 int64_t i_start = p_sys->i_ssnd_start;
299 int64_t i_end = p_sys->i_ssnd_end > 0 ? p_sys->i_ssnd_end : stream_Size( p_demux->s );
300
301 f = (double) va_arg( args, double );
302
303 if( i_start < i_end )
304 {
305 int i_frame = (f * ( i_end - i_start )) / p_sys->i_ssnd_fsize;
306 int64_t i_new = i_start + i_frame * p_sys->i_ssnd_fsize;
307
308 if( stream_Seek( p_demux->s, i_new ) )
309 {
310 return VLC_EGENERIC;
311 }
312 p_sys->i_time = (int64_t)1000000 * i_frame / p_sys->fmt.audio.i_rate;
313 return VLC_SUCCESS;
314 }
315 return VLC_EGENERIC;
316 }
I have attached an example AIFF file which causes the DoS condition.