shithub: sox

Download patch

ref: 1e0a00d4e1d42f775a426519c97fbb2e7a648fe5
parent: 093de989f1568bfeebe8ddf43ee818d3eae43ef1
author: Mans Rullgard <mans@mansr.com>
date: Fri Aug 7 08:27:46 EDT 2020

wav: simplify extended fmt chunk handling [bug #198]

If the fmt chunk is longer than 16 bytes, the following two bytes
are the cbSize field.  Always read this if present, then use it as
needed depending on the format tag.

This also fixes a bogus warning message when reading floating-point
wav files.

--- a/src/wav.c
+++ b/src/wav.c
@@ -401,25 +401,36 @@
     lsx_readw(ft, &wBitsPerSample);      /* bits per sample per channel */
     len -= 16;
 
+    /* non-PCM formats except alaw and mulaw formats have extended fmt chunk.
+     * Check for those cases.
+     */
+    if (wav->formatTag != WAVE_FORMAT_PCM &&
+        wav->formatTag != WAVE_FORMAT_ALAW &&
+        wav->formatTag != WAVE_FORMAT_MULAW &&
+        len < 2)
+        lsx_warn("WAVE file missing extended part of fmt chunk");
+
+    if (len >= 2) {
+        lsx_readw(ft, &wExtSize);
+        len -= 2;
+    }
+
+    if (wExtSize != len) {
+        lsx_fail_errno(ft, SOX_EOF,
+                       "WAVE header error: cbSize inconsistent with fmt size");
+        return SOX_EOF;
+    }
+
     if (wav->formatTag == WAVE_FORMAT_EXTENSIBLE) {
-        uint16_t extensionSize;
         uint16_t numberOfValidBits;
         uint32_t speakerPositionMask;
         uint16_t subFormatTag;
 
-        if (len < 2) {
+        if (len < 22) {
             lsx_fail_errno(ft, SOX_EHDR, "WAVE file fmt chunk is too short");
             return SOX_EOF;
         }
 
-        lsx_readw(ft, &extensionSize);
-        len -= 2;
-
-        if (extensionSize < 22) {
-            lsx_fail_errno(ft, SOX_EHDR, "WAVE file fmt chunk is too short");
-            return SOX_EOF;
-        }
-
         lsx_readw(ft, &numberOfValidBits);
         lsx_readdw(ft, &speakerPositionMask);
         lsx_readw(ft, &subFormatTag);
@@ -484,26 +495,6 @@
         ft->signal.rate = dwSamplesPerSecond;
     else
         lsx_report("User options overriding rate read in .wav header");
-
-    /* non-PCM formats except alaw and mulaw formats have extended fmt chunk.
-     * Check for those cases.
-     */
-    if (wav->formatTag != WAVE_FORMAT_PCM &&
-        wav->formatTag != WAVE_FORMAT_ALAW &&
-        wav->formatTag != WAVE_FORMAT_MULAW) {
-        if (len >= 2) {
-            lsx_readw(ft, &wExtSize);
-            len -= 2;
-        } else {
-            lsx_warn("wave header missing extended part of fmt chunk");
-        }
-    }
-
-    if (wExtSize > len) {
-        lsx_fail_errno(ft, SOX_EOF,
-                       "wave header error: wExtSize inconsistent with wFmtLen");
-        return SOX_EOF;
-    }
 
     switch (wav->formatTag) {
     case WAVE_FORMAT_ADPCM: