Project: libsndfile (libsndfile/libsndfile), language: c++
Vulnerability instance: libsndfile.cve-2018-19432
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/erikd/libsndfile/issues/427
## Description:
Issue: erikd/libsndfile#427
Title: out of bounds read in sf_write_int
State: closed
Created by: YourButterfly
Created at: 2018-11-22 03:19:43+00:00

Issue Body:
## version
libsndfile: Version released 1.0.28 

## description
An issue was discovered in libsndfile 1.0.28. There is an out of bounds read at function sf_write_int, will lead to a denial of service or the others.
```shell
./sndfile-deinterleave tmp/id\:000000\,sig\:06\,src\:000000\,op\:havoc\,rep\:16
Input file : tmp/id:000000,sig:06,src:000000,op:havoc,rep:16
Output files :
    tmp/id:000000,sig:06,src:000000,op:havoc,rep:16_00
    tmp/id:000000,sig:06,src:000000,op:havoc,rep:16_01
......
    tmp/id:000000,sig:06,src:000000,op:havoc,rep:16_254
AddressSanitizer:DEADLYSIGNAL
=================================================================
==49998==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7fb21f1413c6 bp 0x7ffe8d3042c0 sp 0x7ffe8d27ba80 T0)
==49998==The signal is caused by a READ memory access.
==49998==Hint: address points to the zero page.
    #0 0x7fb21f1413c5 in sf_write_int /home/pwd/fuzz/fuzz-wavpack/libsndfile-1.0.28/src/sndfile.c:2257:2
    #1 0x5137b2 in deinterleave_int /home/pwd/fuzz/fuzz-wavpack/libsndfile-1.0.28/programs/sndfile-deinterleave.c:171:4
    #2 0x5137b2 in main /home/pwd/fuzz/fuzz-wavpack/libsndfile-1.0.28/programs/sndfile-deinterleave.c:134
    #3 0x7fb21e138b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #4 0x41a519 in _start (/home/pwd/fuzz/fuzz-wavpack/libsndfile-1.0.28/installed-asan/bin/sndfile-deinterleave+0x41a519)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /home/pwd/fuzz/fuzz-wavpack/libsndfile-1.0.28/src/sndfile.c:2257:2 in sf_write_int
==49998==ABORTING
```

## debug info
In function deinterleave_int,  'ch' is 0x10 , leads to the array bounds, and then crash in function sf_write_int .
```txt
// source:sndfile-deinterleave.c+170 
    165	 	do
    166	 	{	read_len = sf_readf_int (state->infile, state->din.i, BUFFER_LEN) ;
    167	 
    168	 		for (ch = 0 ; ch < state->channels ; ch ++)
    169	 		{	for (k = 0 ; k < read_len ; k++)
		// state=0x00007ffffff75438  →  [...]  →  0x0000000000000000, ch=0x10, k=0x0
 →  170	 				state->dout.i [k] = state->din.i [k * state->channels + ch] ;
    171	 			sf_write_int (state->outfile [ch], state->dout.i, read_len) ;
    172	 			} ;
    173	 		}
    174	 	while (read_len > 0) ;
    175	 
gef➤  p state->channels
$3 = 0xff
gef➤  p state->outfile 
$6 = {0x555555769300, 0x55555576c800, 0x55555576fd00, 0x555555773200, 0x555555776700, 0x555555779c00, 0x55555577d100, 0x555555780600, 0x555555783b00, 0x555555787000, 0x55555578a500, 0x55555578da00, 0x555555790f00, 0x555555794400, 0x555555797900, 0x55555579ae00}

......
// source:sndfile.c+2257
		// sndfile=0x00007ffffff75408  →  0xf62d0000f7db0000, psf=0x00007ffffff75410  →  0xf62d0000f7db0000
 → 2257	 	VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ;
   2258	 
   2259	 	if (len <= 0)
   2260	 	{	psf->error = SFE_NEGATIVE_RW_LEN ;
   2261	 		return 0 ;
   2262	 		} 
[#0] Id 1, Name: "sndfile-deinter", stopped, reason: SIGSEGV
```

[poc.tar.gz](https://github.com/erikd/libsndfile/files/2606482/poc.tar.gz)

## others
this bug is reported by pwd@360TeamSeri0us, 
please send email to   teamSeri0us360@gmail.com if you have some quetion.




Comments:
Comment by carnil on 2018-11-22 20:19:24+00:00:
This issue was assigned CVE-2018-19432

---

Comment by evpobr on 2018-11-23 04:30:24+00:00:
Thanks. @erikd usually does bugfixing. Can you check this bug exists in `master` brunch?

---

Comment by YourButterfly on 2018-11-23 06:59:26+00:00:
Thanks, this bug is fixed by checking out the value of channels, in master brunch.
Can you keep this issue active before a new version is released?

Have a nice day!

---

Comment by evpobr on 2018-11-23 07:15:17+00:00:
Probably duplicate of #346. Fixed by 6f32662.

---

Comment by rjoshi18 on 2018-12-04 09:24:14+00:00:
Hi @YourButterfly @evpobr  could You please confirm, whether this issue got fixed or not?

---

Comment by erikd on 2018-12-04 22:52:52+00:00:
> could You please confirm, whether this issue got fixed or not?

The code is here in github. Is it not possible for you to confirm?


---

Comment by hlef on 2018-12-07 11:16:10+00:00:
The poc defines a number of channels = 255 > MAX_CHANNELS (=16). This triggers a first overflow which is silently ignored in sndfile-deinterleave.c:main:

```
for (ch = 0 ; ch < state.channels ; ch++) // state.channels is 255 here
{	...

	if ((state.outfile [ch] = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL) // state.outfile is a char[16] array
	{	printf ("Not able to open output file '%s'\n%s\n", filename, sf_strerror (NULL)) ;
		exit (1) ;
	} ;

	...
} ;
```

This is the main problem. If a file defines a number of channels > MAX_CHANNELS we should either artificially reduce the number of channels or reject it.

Hence this issue is not a duplicate of #346 but rather a duplicate of #397 fixed in aaea680337267bfb6d2544da878890ee7f1c5077.

(FTR, issue #397 was assigned CVE-2018-13139)

---

Comment by erikd on 2019-01-02 09:27:19+00:00:
This is fixed in Git HEAD:
```
> programs/sndfile-deinterleave oob_sf_write_int\:2257 

Error : Input file 'oob_sf_write_int:2257' has too many (255) channels. Limit is 16.
```
as @hlef say, it was fixed in commit aaea680.

Attachments:
https://github.com/erikd/libsndfile/files/2606482/poc.tar.gz

Commit References:
aaea680337267bfb6d2544da878890ee7f1c5077

Build script:
#!/bin/bash
# Default build script template for C/C++ projects
set -eu

# Define configuration options
CONFIG_OPTS="--disable-shared"
CMAKE_OPTS="-DCMAKE_BUILD_TYPE=Debug"
MAKE_OPTS="-j$(nproc)"
BUILD_DIR="build"

# 1. Run build preparation scripts if they exist
for prep_script in buildconf autogen.sh bootstrap; do
  if [ -x "$prep_script" ]; then
    echo "Running $prep_script..."
    ./$prep_script
    break
  elif [ -f "$prep_script" ]; then
    echo "Found $prep_script but it's not executable, setting permissions..."
    chmod +x $prep_script
    ./$prep_script
    break
  fi
done

# 2. Handle different build systems
if [ -f "configure" ]; then
  echo "Found configure script, running with options: $CONFIG_OPTS"
  ./configure $CONFIG_OPTS

  echo "Building with make $MAKE_OPTS"
  make $MAKE_OPTS
elif [ -f "CMakeLists.txt" ]; then
  echo "Found CMakeLists.txt, using CMake build system"
  mkdir -p $BUILD_DIR
  cd $BUILD_DIR
  cmake $CMAKE_OPTS ..
  make $MAKE_OPTS
elif [ -f "Makefile" ] || [ -f "makefile" ]; then
  echo "Found Makefile, building with make $MAKE_OPTS"
  make $MAKE_OPTS
elif [ -f "meson.build" ]; then
  echo "Found meson.build, using Meson build system"
  mkdir -p $BUILD_DIR
  meson setup $BUILD_DIR .
  cd $BUILD_DIR
  ninja
elif [ -f "GNUmakefile" ]; then
  echo "Found GNUmakefile, building with make $MAKE_OPTS"
  make $MAKE_OPTS
elif [ -d ".git" ] && [ -f "Makefile.am" ]; then
  echo "Found Makefile.am, running autoreconf"
  autoreconf -i
  ./configure $CONFIG_OPTS
  make $MAKE_OPTS
else
  echo "WARNING: No recognized build system found!"
  echo "Trying generic approach:"
  
  # Try to detect common source patterns and compile them
  if ls *.c >/dev/null 2>&1 || ls *.cpp >/dev/null 2>&1 || ls *.cc >/dev/null 2>&1; then
    echo "Found C/C++ source files, attempting direct compilation"
    if ls *.cpp >/dev/null 2>&1 || ls *.cc >/dev/null 2>&1; then
      CXX=${CXX:-g++}
      echo "Compiling C++ sources with $CXX"
      $CXX -g -O1 -fsanitize=address -fno-omit-frame-pointer -o main *.cpp *.cc 2>/dev/null || true
    elif ls *.c >/dev/null 2>&1; then
      CC=${CC:-gcc}
      echo "Compiling C sources with $CC"
      $CC -g -O1 -fsanitize=address -fno-omit-frame-pointer -o main *.c 2>/dev/null || true
    fi
  fi
fi

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN git clone https://github.com/libsndfile/libsndfile libsndfile
RUN git -C libsndfile checkout 1d928bffdb65e827c3e7d17ece0e123b4a70ec6c
WORKDIR $SRC/libsndfile
COPY build.sh $SRC/

Additional files: