wav gsm playback and encoding is broken because the wav.c patch to avoid division by 0 introduced a regression. Debian has a fix for an older version of sox from Helmut Grohne <helmut () subdivi ! de>. This patch is from Steffen Nurpmeso <steffen () sdaoden ! eu> who applied it against git. I added a tweak to not recalculate wave->numSamples for wav gsm files, which is where division by 0 happens. Apparently, gsm has variable bits_per_sample, so 0 is an acceptable value.
Steffen's diff: https://marc.info/?l=oss-security&m=167882517702862&w=2 tweak: https://marc.info/?l=oss-security&m=168026419507884&w=2 Test cases ---------- With this diff these two test cases pass. 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. incorrect 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--- Feedback is welcome. OK? Index: Makefile =================================================================== RCS file: /cvs/ports/audio/sox/Makefile,v retrieving revision 1.76 diff -u -p -u -p -r1.76 Makefile --- Makefile 22 Feb 2023 16:27:38 -0000 1.76 +++ Makefile 3 Apr 2023 22:51:32 -0000 @@ -5,7 +5,7 @@ V= 14.4.2pl20210509 GIT_V= 14.4.3git DISTNAME= sox-${V} SHARED_LIBS += sox 4.1 # 3.0 -REVISION= 0 +REVISION= 1 CATEGORIES= audio HOMEPAGE= http://sox.sourceforge.net/ Index: patches/patch-src_wav_c =================================================================== RCS file: /cvs/ports/audio/sox/patches/patch-src_wav_c,v retrieving revision 1.3 diff -u -p -u -p -r1.3 patch-src_wav_c --- patches/patch-src_wav_c 22 Feb 2023 15:03:03 -0000 1.3 +++ patches/patch-src_wav_c 3 Apr 2023 22:51:32 -0000 @@ -1,14 +1,22 @@ https://marc.info/?l=oss-security&m=167571683504082&w=2 +unbreak wav gsm +see: +https://marc.info/?l=oss-security&m=167882517702862&w=2 +https://marc.info/?l=oss-security&m=168026419507884&w=2 + Index: src/wav.c --- src/wav.c.orig +++ src/wav.c -@@ -654,6 +654,12 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len +@@ -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) -+ { ++ 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; + } @@ -16,3 +24,68 @@ Index: src/wav.c /* non-PCM formats except alaw and mulaw formats have extended fmt chunk. * Check for those cases. */ +@@ -963,7 +972,11 @@ static int startread(sox_format_t *ft) + #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 +1361,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 +1459,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 +1571,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 +1613,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 +1633,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;