CVE-2018-10536: Out-of-bounds Write (CWE-787)
value: An issue was discovered in WavPack 5.1.0 and earlier. The WAV parser component contains a vulnerability that allows writing to memory because ParseRiffHeaderConfig in riff.c does not reject multiple format chunks.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2018-04-29T15:29Z
Repository: https://github.com/dbry/WavPack
Language: C
Files changed: cli/riff.c, cli/wave64.c
Commit date: 2018-04-24 22:18:07 -0700
Commit message: issue #30 issue #31 issue #32: no multiple format chunks in WAV or W64

Diff: diff --git a/cli/riff.c b/cli/riff.c
index 7bddf63..5d6452e 100644
--- a/cli/riff.c
+++ b/cli/riff.c
@@ -51,11 +51,11 @@ typedef struct {
 
 extern int debug_logging_mode;
 
 int ParseRiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, WavpackContext *wpc, WavpackConfig *config)
 {
-    int is_rf64 = !strncmp (fourcc, "RF64", 4), got_ds64 = 0;
+    int is_rf64 = !strncmp (fourcc, "RF64", 4), got_ds64 = 0, format_chunk = 0;
     int64_t total_samples = 0, infilesize;
     RiffChunkHeader riff_chunk_header;
     ChunkHeader chunk_header;
     WaveHeader WaveHeader;
     DS64Chunk ds64_chunk;
@@ -138,10 +138,15 @@ int ParseRiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpack
             }
         }
         else if (!strncmp (chunk_header.ckID, "fmt ", 4)) {     // if it's the format chunk, we want to get some info out of there and
             int supported = TRUE, format;                        // make sure it's a .wav file we can handle
 
+            if (format_chunk++) {
+                error_line ("%s is not a valid .WAV file!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
+
             if (chunk_header.ckSize < 16 || chunk_header.ckSize > sizeof (WaveHeader) ||
                 !DoReadFile (infile, &WaveHeader, chunk_header.ckSize, &bcount) ||
                 bcount != chunk_header.ckSize) {
                     error_line ("%s is not a valid .WAV file!", infilename);
                     return WAVPACK_SOFT_ERROR;
diff --git a/cli/wave64.c b/cli/wave64.c
index fa928a0..0388dc7 100644
--- a/cli/wave64.c
+++ b/cli/wave64.c
@@ -51,10 +51,11 @@ int ParseWave64HeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
 {
     int64_t total_samples = 0, infilesize;
     Wave64ChunkHeader chunk_header;
     Wave64FileHeader filehdr;
     WaveHeader WaveHeader;
+    int format_chunk = 0;
     uint32_t bcount;
 
     infilesize = DoGetFileSize (infile);
     memcpy (&filehdr, fourcc, 4);
 
@@ -102,10 +103,15 @@ int ParseWave64HeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
         // make sure it's a .wav file we can handle
 
         if (!memcmp (chunk_header.ckID, fmt_guid, sizeof (fmt_guid))) {
             int supported = TRUE, format;
 
+            if (format_chunk++) {
+                error_line ("%s is not a valid .W64 file!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
+
             chunk_header.ckSize = (chunk_header.ckSize + 7) & ~7L;
 
             if (chunk_header.ckSize < 16 || chunk_header.ckSize > sizeof (WaveHeader) ||
                 !DoReadFile (infile, &WaveHeader, (uint32_t) chunk_header.ckSize, &bcount) ||
                 bcount != chunk_header.ckSize) {

Vulnerable code:     int is_rf64 = !strncmp (fourcc, "RF64", 4), got_ds64 = 0;
Fixed code:     int is_rf64 = !strncmp (fourcc, "RF64", 4), got_ds64 = 0, format_chunk = 0;
            if (format_chunk++) {
                error_line ("%s is not a valid .WAV file!", infilename);
                return WAVPACK_SOFT_ERROR;
            }

    int format_chunk = 0;
            if (format_chunk++) {
                error_line ("%s is not a valid .W64 file!", infilename);
                return WAVPACK_SOFT_ERROR;
            }