Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 30 Mar 2023 16:22:20 -0700
From: Nam Nguyen <namn@...keley.edu>
To: oss-security@...ts.openwall.com
Cc: Steffen Nurpmeso <steffen@...oden.eu>
Subject: Re: Re: sox: patches for old vulnerabilities

Steffen Nurpmeso writes:

> Steffen Nurpmeso wrote in
>  <20230314201652.RlbWr%steffen@...oden.eu>:
>  ...
>  ||Helmut Grohne wrote in
>  || <20230314110138.GA1192267@...divi.de>:
>  |||On Fri, Feb 03, 2023 at 09:44:47PM +0100, Helmut Grohne wrote:
>  |||>  * CVE-2021-33844
>  |||
>  |||The original fix for this issue would cause a regression. After applying
>  |||it, sox would be unable to decode WAV GSM files. This has been reported
>  ...
>
> Today i got a nice email from Nam Nguyen who pointed out that my
> last patch to this topic (also) introduced a bug.  So i downloaded
> libGSM and yes he was right.  So on top of them all a partial undo
> of the last is necessary; i will attach the full diff, too.

I propose keeping that check in order to fix the regression of not
opening wav gsm files.

Steffn Nurpmeso's patch with tweaks can be found inline at the end of
this email. This patch retains the line 654 hunk and adds line 961 hunk
to avoid dividing by 0 for wav gsm files. wav->numSamples is calculated
similarly to debian's version of sox.

Feedback is welcome as I am not familiar with the code base.

debian's sox:
--8<---------------cut here---------------start------------->8---
    943     case WAVE_FORMAT_GSM610:
    944         wav->numSamples = ((qwDataLength / wav->blockAlign) * wav->samplesPerBlock);
    945         wavgsminit(ft);
    946         ft->signal.length = wav->numSamples*ft->signal.channels;
    947         break;
    948
    949     default:
    950         wav->numSamples = div_bits(qwDataLength, ft->encoding.bits_per_sample) / ft->signal.channels;
    951         ft->signal.length = wav->numSamples * ft->signal.channels;
    952     }
--8<---------------cut here---------------end--------------->8---


new 961 hunk:
--8<---------------cut here---------------start------------->8---
    967 #ifdef HAVE_LIBGSM
    968     case WAVE_FORMAT_GSM610:
    969         wav->numSamples = qwDataLength / wav->blockAlign * wav->samplesPerBlock;
    970         wavgsminit(ft);
    971         break;
    972 #endif
    973
    974     }
    975
    976     if ((!wav->numSamples)
    977 #ifdef HAVE_LIBGSM
    978         && wav->formatTag != WAVE_FORMAT_GSM610
    979 #endif
    980     )
    981         wav->numSamples = div_bits(qwDataLength, ft->encoding.bits_per_sample)
    982             / ft->signal.channels;
--8<---------------cut here---------------end--------------->8---
    
Test cases
----------
Test case 1: convert /dev/null to bug.wav (wav gsm) and then convert
bug.wav to fail.wav.

This test case is expected to pass.

failing output:
--8<---------------cut here---------------start------------->8---
$ sox -t raw -r 44100 -e signed-integer -b 8 /dev/null -t wav -e gsm-full-rate bug.wav
$ sox bug.wav fail.wav
sox FAIL formats: can't open input file `bug.wav': WAV file bits per sample is zero
--8<---------------cut here---------------end--------------->8---


correct output (which this provides):
--8<---------------cut here---------------start------------->8---
$ sox -t raw -r 44100 -e signed-integer -b 8 /dev/null -t wav -e gsm-full-rate bug.wav
$ sox bug.wav fail.wav
$ file fail.wav
fail.wav: RIFF (little-endian) data, WAVE audio, GSM 6.10, mono 44100 Hz
--8<---------------cut here---------------end--------------->8---

Test case 2: convert flac to wav gsm. then, convert wav gsm to wav gsm.

This test case is expected to pass.
--8<---------------cut here---------------start------------->8---
$ sox -t flac -r 44100 -e signed-integer -b 16 song.flac -t wav -e gsm-full-rate ok.wav
$ sox ok.wav ok2.wav
--8<---------------cut here---------------end--------------->8---

inline patch
------------

https://marc.info/?l=oss-security&m=167571683504082&w=2

unbreak wav gsm
https://marc.info/?l=oss-security&m=167882517702862&w=2

Index: src/wav.c
--- src/wav.c.orig
+++ src/wav.c
@@ -654,6 +654,15 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len
     if (err)
         return SOX_EOF;
 
+    if (wav->bitsPerSample == 0
+#ifdef HAVE_LIBGSM
+            && wav->formatTag != WAVE_FORMAT_GSM610
+#endif
+    ){
+        lsx_fail_errno(ft, SOX_EHDR, "WAV file bits per sample is zero");
+        return SOX_EOF;
+    }
+
     /* non-PCM formats except alaw and mulaw formats have extended fmt chunk.
      * Check for those cases.
      */
@@ -961,9 +970,14 @@ static int startread(sox_format_t *ft)
         wavgsminit(ft);
         break;
 #endif
+
     }
 
-    if (!wav->numSamples)
+    if ((!wav->numSamples)
+#ifdef HAVE_LIBGSM
+            && wav->formatTag != WAVE_FORMAT_GSM610
+#endif
+    )
         wav->numSamples = div_bits(qwDataLength, ft->encoding.bits_per_sample)
             / ft->signal.channels;
 
@@ -1348,8 +1362,10 @@ static int wavwritehdr(sox_format_t * ft, int second_h
         (dwSamplesWritten + wSamplesPerBlock - 1) / wSamplesPerBlock;
     dwDataLength = blocksWritten * wBlockAlign;
 
+#ifdef HAVE_LIBGSM
     if (wFormatTag == WAVE_FORMAT_GSM610)
         dwDataLength = (dwDataLength+1) & ~1u; /* round up to even */
+#endif
 
     if (wFormatTag == WAVE_FORMAT_PCM && (wBitsPerSample > 16 || wChannels > 2)
         && strcmp(ft->filetype, "wavpcm")) {
@@ -1444,9 +1460,11 @@ static int wavwritehdr(sox_format_t * ft, int second_h
             lsx_writew(ft, (uint16_t)(lsx_ms_adpcm_i_coef[i][1]));
         }
         break;
+#ifdef HAVE_LIBGSM
         case WAVE_FORMAT_GSM610:
         lsx_writew(ft, wSamplesPerBlock);
         break;
+#endif
         default:
         break;
     }
@@ -1554,7 +1572,9 @@ static int stopwrite(sox_format_t * ft)
 
         /* Add a pad byte if the number of data bytes is odd.
            See wavwritehdr() above for the calculation. */
+#ifdef HAVE_LIBGSM
         if (wav->formatTag != WAVE_FORMAT_GSM610)
+#endif
           lsx_padbytes(ft, (size_t)((wav->numSamples + wav->samplesPerBlock - 1)/wav->samplesPerBlock*wav->blockAlign) % 2);
 
         free(wav->packet);
@@ -1594,6 +1614,7 @@ static int seek(sox_format_t * ft, uint64_t offset)
 
   if (ft->encoding.bits_per_sample & 7)
     lsx_fail_errno(ft, SOX_ENOTSUP, "seeking not supported with this encoding");
+#ifdef HAVE_LIBGSM
   else if (wav->formatTag == WAVE_FORMAT_GSM610) {
     int alignment;
     size_t gsmoff;
@@ -1613,7 +1634,9 @@ static int seek(sox_format_t * ft, uint64_t offset)
           new_offset += (wav->samplesPerBlock - alignment);
       wav->numSamples = ft->signal.length - (new_offset / ft->signal.channels);
     }
-  } else {
+  }
+#endif /* HAVE_LIBGSM */
+  else {
     double wide_sample = offset - (offset % ft->signal.channels);
     double to_d = wide_sample * ft->encoding.bits_per_sample / 8;
     off_t to = to_d;

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.