CVE-2018-10537: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: An issue was discovered in WavPack 5.1.0 and earlier. The W64 parser component contains a vulnerability that allows writing to memory because ParseWave64HeaderConfig in wave64.c does not reject multiple format chunks.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
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;
            }