Permalink
Browse files

WAV : Avoid divide by zero exception.

Found a couple of instances where a value retrieved from an input
file header was used as the denominator in a division. If the
retrieved value is zero it results on a divide by zero error.

Found using the afl (http://lcamtuf.coredump.cx/afl/) fuzzer.
  • Loading branch information...
erikd committed Nov 28, 2014
1 parent 4de9a59 commit a0177b4076642fd92a3bc6409debcbd0ae7f32ac
Showing with 22 additions and 11 deletions.
  1. +1 −0 src/common.h
  2. +1 −0 src/sndfile.c
  3. +20 −11 src/wav_w64.c
View
@@ -599,6 +599,7 @@ enum
SFE_WAV_BAD_LIST,
SFE_WAV_ADPCM_NOT4BIT,
SFE_WAV_ADPCM_CHANNELS,
+ SFE_WAV_ADPCM_SAMPLES,
SFE_WAV_GSM610_FORMAT,
SFE_WAV_UNKNOWN_CHUNK,
SFE_WAV_WVPK_DATA,
View
@@ -147,6 +147,7 @@ ErrorStruct SndfileErrors [] =
{ SFE_WAV_ADPCM_NOT4BIT , "Error in ADPCM WAV file. Invalid bit width." },
{ SFE_WAV_ADPCM_CHANNELS , "Error in ADPCM WAV file. Invalid number of channels." },
+ { SFE_WAV_ADPCM_SAMPLES , "Error in ADPCM WAV file. Invalid number of samples per block." },
{ SFE_WAV_GSM610_FORMAT , "Error in GSM610 WAV file. Invalid format chunk." },
{ SFE_AIFF_NO_FORM , "Error in AIFF file, bad 'FORM' marker." },
View
@@ -197,7 +197,7 @@ wav_w64_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
case WAVE_FORMAT_ALAW :
case WAVE_FORMAT_MULAW :
- if (wav_fmt->min.bytespersec / wav_fmt->min.blockalign != wav_fmt->min.samplerate)
+ if (wav_fmt->min.bytespersec != wav_fmt->min.samplerate * wav_fmt->min.blockalign)
psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, wav_fmt->min.samplerate * wav_fmt->min.blockalign) ;
else
psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ;
@@ -215,17 +215,21 @@ wav_w64_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
if (wav_fmt->min.channels < 1 || wav_fmt->min.channels > 2)
return SFE_WAV_ADPCM_CHANNELS ;
- bytesread +=
- psf_binheader_readf (psf, "22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ;
+ bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ;
+ psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->ima.extrabytes) ;
+ if (wav_fmt->ima.samplesperblock < 1)
+ { psf_log_printf (psf, " Samples/Block : %d (should be > 0)\n", wav_fmt->ima.samplesperblock) ;
+ return SFE_WAV_ADPCM_SAMPLES ;
+ }
+ else
+ psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ;
bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock ;
if (wav_fmt->ima.bytespersec != (unsigned) bytespersec)
psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ima.bytespersec, bytespersec) ;
else
psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ima.bytespersec) ;
- psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->ima.extrabytes) ;
- psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ;
break ;
case WAVE_FORMAT_MS_ADPCM :
@@ -234,9 +238,16 @@ wav_w64_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2)
return SFE_WAV_ADPCM_CHANNELS ;
- bytesread +=
- psf_binheader_readf (psf, "222", &(wav_fmt->msadpcm.extrabytes),
- &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ;
+ bytesread += psf_binheader_readf (psf, "222", &(wav_fmt->msadpcm.extrabytes),
+ &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ;
+
+ psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->msadpcm.extrabytes) ;
+ if (wav_fmt->ima.samplesperblock < 1)
+ { psf_log_printf (psf, " Samples/Block : %d (should be > 0)\n", wav_fmt->ima.samplesperblock) ;
+ return SFE_WAV_ADPCM_SAMPLES ;
+ }
+ else
+ psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ;
bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / wav_fmt->msadpcm.samplesperblock ;
if (wav_fmt->min.bytespersec == (unsigned) bytespersec)
@@ -246,8 +257,6 @@ wav_w64_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
else
psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ;
- psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->msadpcm.extrabytes) ;
- psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->msadpcm.samplesperblock) ;
if (wav_fmt->msadpcm.numcoeffs > ARRAY_LEN (wav_fmt->msadpcm.coeffs))
{ psf_log_printf (psf, " No. of Coeffs : %d (should be <= %d)\n", wav_fmt->msadpcm.numcoeffs, ARRAY_LEN (wav_fmt->msadpcm.coeffs)) ;
wav_fmt->msadpcm.numcoeffs = ARRAY_LEN (wav_fmt->msadpcm.coeffs) ;
@@ -287,7 +296,7 @@ wav_w64_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
break ;
case WAVE_FORMAT_EXTENSIBLE :
- if (wav_fmt->ext.bytespersec / wav_fmt->ext.blockalign != wav_fmt->ext.samplerate)
+ if (wav_fmt->ext.bytespersec != wav_fmt->ext.samplerate * wav_fmt->ext.blockalign)
psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ;
else
psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ext.bytespersec) ;

0 comments on commit a0177b4

Please sign in to comment.