CVE-2018-10538: Out-of-bounds Write (CWE-787)
value: An issue was discovered in WavPack 5.1.0 and earlier for WAV input. Out-of-bounds writes can occur because ParseRiffHeaderConfig in riff.c does not validate the sizes of unknown chunks before attempting memory allocation, related to a lack of integer-overflow protection within a bytes_to_copy calculation and subsequent malloc call, leading to insufficient memory allocation.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 5.5
Published: 2018-04-29T15:29Z
Repository: https://github.com/dbry/WavPack
Language: C
Files changed: cli/dsdiff.c, cli/riff.c, cli/wave64.c
Commit date: 2018-04-24 17:27:01 -0700
Commit message: issue #33, sanitize size of unknown chunks before malloc()

Diff: diff --git a/cli/dsdiff.c b/cli/dsdiff.c
index c016df9..fa56bbb 100644
--- a/cli/dsdiff.c
+++ b/cli/dsdiff.c
@@ -277,11 +277,18 @@ int ParseDsdiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
             break;
         }
         else {          // just copy unknown chunks to output file
 
             int bytes_to_copy = (int)(((dff_chunk_header.ckDataSize) + 1) & ~(int64_t)1);
-            char *buff = malloc (bytes_to_copy);
+            char *buff;
+
+            if (bytes_to_copy < 0 || bytes_to_copy > 4194304) {
+                error_line ("%s is not a valid .DFF file!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
+
+            buff = malloc (bytes_to_copy);
 
             if (debug_logging_mode)
                 error_line ("extra unknown chunk \"%c%c%c%c\" of %d bytes",
                     dff_chunk_header.ckID [0], dff_chunk_header.ckID [1], dff_chunk_header.ckID [2],
                     dff_chunk_header.ckID [3], dff_chunk_header.ckDataSize);
diff --git a/cli/riff.c b/cli/riff.c
index de98c1e..7bddf63 100644
--- a/cli/riff.c
+++ b/cli/riff.c
@@ -284,11 +284,18 @@ int ParseRiffHeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpack
             break;
         }
         else {          // just copy unknown chunks to output file
 
             int bytes_to_copy = (chunk_header.ckSize + 1) & ~1L;
-            char *buff = malloc (bytes_to_copy);
+            char *buff;
+
+            if (bytes_to_copy < 0 || bytes_to_copy > 4194304) {
+                error_line ("%s is not a valid .WAV file!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
+
+            buff = malloc (bytes_to_copy);
 
             if (debug_logging_mode)
                 error_line ("extra unknown chunk \"%c%c%c%c\" of %d bytes",
                     chunk_header.ckID [0], chunk_header.ckID [1], chunk_header.ckID [2],
                     chunk_header.ckID [3], chunk_header.ckSize);
diff --git a/cli/wave64.c b/cli/wave64.c
index 591d640..fa928a0 100644
--- a/cli/wave64.c
+++ b/cli/wave64.c
@@ -239,11 +239,18 @@ int ParseWave64HeaderConfig (FILE *infile, char *infilename, char *fourcc, Wavpa
             config->sample_rate = WaveHeader.SampleRate;
             break;
         }
         else {          // just copy unknown chunks to output file
             int bytes_to_copy = (chunk_header.ckSize + 7) & ~7L;
-            char *buff = malloc (bytes_to_copy);
+            char *buff;
+
+            if (bytes_to_copy < 0 || bytes_to_copy > 4194304) {
+                error_line ("%s is not a valid .W64 file!", infilename);
+                return WAVPACK_SOFT_ERROR;
+            }
+
+            buff = malloc (bytes_to_copy);
 
             if (debug_logging_mode)
                 error_line ("extra unknown chunk \"%c%c%c%c\" of %d bytes",
                     chunk_header.ckID [0], chunk_header.ckID [1], chunk_header.ckID [2],
                     chunk_header.ckID [3], chunk_header.ckSize);

Vulnerable code:             char *buff = malloc (bytes_to_copy);
            char *buff = malloc (bytes_to_copy);
            char *buff = malloc (bytes_to_copy);
Fixed code:             char *buff;

            if (bytes_to_copy < 0 || bytes_to_copy > 4194304) {
                error_line ("%s is not a valid .DFF file!", infilename);
                return WAVPACK_SOFT_ERROR;
            }

            buff = malloc (bytes_to_copy);
            char *buff;

            if (bytes_to_copy < 0 || bytes_to_copy > 4194304) {
                error_line ("%s is not a valid .WAV file!", infilename);
                return WAVPACK_SOFT_ERROR;
            }

            buff = malloc (bytes_to_copy);
            char *buff;

            if (bytes_to_copy < 0 || bytes_to_copy > 4194304) {
                error_line ("%s is not a valid .W64 file!", infilename);
                return WAVPACK_SOFT_ERROR;
            }

            buff = malloc (bytes_to_copy);