Vulnerability: WavPack 5.1 and earlier is affected by: CWE 369: Divide by Zero. The impact is: Divide by zero can lead to sudden crash of a software/service that tries to parse a .wav file. The component is: ParseDsdiffHeaderConfig (dsdiff.c:282). The attack vector is: Maliciously crafted .wav file. The fixed version is: After commit https://github.com/dbry/WavPack/commit/4c0faba32fddbd0745cbfaf1e1aeb3da5d35b9fc.
Vulnerability ID: CVE-2019-1010315
CWE: CWE-369
Severity score: 2.9
Project: https://github.com/dbry/WavPack
Published: 2019-07-11
File: cli/dsdiff.c
Commit message: issue #65: make sure DSDIFF files have a valid channel count
Commit author: David Bryant

Vulnerable version (before fix):
 int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa              if (!strncmp (prop_chunk, "SND ", 4)) {                 char *cptr = prop_chunk + 4, *eptr = prop_chunk + dff_chunk_header.ckDataSize;                 uint16_t numChannels, chansSpecified, chanMask = 0;                 uint32_t sampleRate;                  while (eptr - cptr >= sizeof (dff_chunk_header)) { int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa                              chansSpecified = (int)(dff_chunk_header.ckDataSize - sizeof (numChannels)) / 4;                              if (numChannels < chansSpecified || numChannels < 1) {                                 error_line ("%s is not a valid .DFF file!", infilename);                                 free (prop_chunk);                                 return WAVPACK_SOFT_ERROR; int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa             free (prop_chunk);         }         else if (!strncmp (dff_chunk_header.ckID, "DSD ", 4)) {             total_samples = dff_chunk_header.ckDataSize / config->num_channels;             break;         }

Fixed version (after fix):
 int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa              if (!strncmp (prop_chunk, "SND ", 4)) {                 char *cptr = prop_chunk + 4, *eptr = prop_chunk + dff_chunk_header.ckDataSize;                 uint16_t numChannels = 0, chansSpecified, chanMask = 0;                 uint32_t sampleRate;                  while (eptr - cptr >= sizeof (dff_chunk_header)) { int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa                              chansSpecified = (int)(dff_chunk_header.ckDataSize - sizeof (numChannels)) / 4;                              if (numChannels < chansSpecified || numChannels < 1 || numChannels > 256) {                                 error_line ("%s is not a valid .DFF file!", infilename);                                 free (prop_chunk);                                 return WAVPACK_SOFT_ERROR; int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa             free (prop_chunk);         }         else if (!strncmp (dff_chunk_header.ckID, "DSD ", 4)) {              if (!config->num_channels) {                 error_line ("%s is not a valid .DFF file!", infilename);                 return WAVPACK_SOFT_ERROR;             }              total_samples = dff_chunk_header.ckDataSize / config->num_channels;             break;         }

Patch:
patch: @@ -180,7 +180,7 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
 
             if (!strncmp (prop_chunk, "SND ", 4)) {
                 char *cptr = prop_chunk + 4, *eptr = prop_chunk + dff_chunk_header.ckDataSize;
-                uint16_t numChannels, chansSpecified, chanMask = 0;
+                uint16_t numChannels = 0, chansSpecified, chanMask = 0;
                 uint32_t sampleRate;
 
                 while (eptr - cptr >= sizeof (dff_chunk_header)) {
@@ -204,7 +204,7 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
 
                             chansSpecified = (int)(dff_chunk_header.ckDataSize - sizeof (numChannels)) / 4;
 
-                            if (numChannels < chansSpecified || numChannels < 1) {
+                            if (numChannels < chansSpecified || numChannels < 1 || numChannels > 256) {
                                 error_line ("%s is not a valid .DFF file!", infilename);
                                 free (prop_chunk);
                                 return WAVPACK_SOFT_ERROR;
@@ -279,6 +279,12 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
             free (prop_chunk);
         }
         else if (!strncmp (dff_chunk_header.ckID, "DSD ", 4)) {
+
+            if (!config->num_channels) {
+                error_line ("%s is not a valid .DFF file!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
+
             total_samples = dff_chunk_header.ckDataSize / config->num_channels;
             break;
         }
path: cli/dsdiff.c