-
Notifications
You must be signed in to change notification settings - Fork 329
Description
Dear soloud Maintainers,
I would like to report some Heap-buffer-overflow and SEGV issues discovered in soloud.
Heap-buffer-overflow (Write) in SoLoud::Wav::loadflac at soloud_wav.cpp:257
Description
The crash occurs within SoLoud::Wav::loadflac at src/audiosource/wav/soloud_wav.cpp:257, which is invoked when loading a crafted audio file (via loadMem). The AddressSanitizer (ASAN) report indicates a WRITE of size 4 occurring 1024 bytes past the end of a very large allocated region (approx 16GB).
Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
Vulnerability Details
- Type: Heap-buffer-overflow (Write)
- Location: src/audiosource/wav/soloud_wav.cpp:257:38
- Function: SoLoud::Wav::loadflac
- Context: The issue seems to trigger during the parsing of FLAC data embedded in a WAV container or loaded as a raw memory file.
Reproduce
- Build soloud and harness with Release optimization and ASAN enabled.
harness.cpp
#include "soloud.h"
#include "soloud_wav.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
if (argc < 2) {
return 1;
}
FILE *f = fopen(argv[1], "rb");
if (!f) {
return 1;
}
fseek(f, 0, SEEK_END);
long len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
if (!buf) {
fclose(f);
return 1;
}
if (fread(buf, 1, len, f) != (size_t)len) {
free(buf);
fclose(f);
return 1;
}
fclose(f);
SoLoud::Soloud soloud;
soloud.init(SoLoud::Soloud::CLIP_ROUNDOFF | SoLoud::Soloud::ENABLE_VISUALIZATION,
SoLoud::Soloud::NULLDRIVER);
SoLoud::Wav wav;
int res = wav.loadMem(buf, len, false, false);
if (res == 0) {
SoLoud::handle h = soloud.play(wav);
soloud.stop(h);
}
soloud.deinit();
free(buf);
return 0;
}
- Run with the crashing file:
./harness repro
ASAN report
=================================================================
==63267==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fd35c8f6c00 at pc 0x5578999a38fe bp 0x7ffd856790d0 sp 0x7ffd856790c8
WRITE of size 4 at 0x7fd35c8f6c00 thread T0
#0 0x5578999a38fd in SoLoud::Wav::loadflac(SoLoud::MemoryFile*) /src/soloud/src/audiosource/wav/soloud_wav.cpp:257:38
#1 0x5578999a45d4 in SoLoud::Wav::loadMem(unsigned char const*, unsigned int, bool, bool) /src/soloud/src/audiosource/wav/soloud_wav.cpp:314:10
#2 0x557899948124 in main /src/soloud/harness.cpp:39:19
#3 0x7fd35ef461c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#4 0x7fd35ef4628a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#5 0x5578998645d4 in _start (/src/soloud/harness+0x395d4) (BuildId: 564525bdfb4ff8144e0982209d7e978677d8be1c)
0x7fd35c8f6c00 is located 1024 bytes after 17179860992-byte region [0x7fcf5c8f8800,0x7fd35c8f6800)
allocated by thread T0 here:
#0 0x557899945ba1 in operator new[](unsigned long) (/src/soloud/harness+0x11aba1) (BuildId: 564525bdfb4ff8144e0982209d7e978677d8be1c)
#1 0x5578999a30e0 in SoLoud::Wav::loadflac(SoLoud::MemoryFile*) /src/soloud/src/audiosource/wav/soloud_wav.cpp:241:11
#2 0x5578999a45d4 in SoLoud::Wav::loadMem(unsigned char const*, unsigned int, bool, bool) /src/soloud/src/audiosource/wav/soloud_wav.cpp:314:10
#3 0x557899948124 in main /src/soloud/harness.cpp:39:19
#4 0x7fd35ef461c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#5 0x7fd35ef4628a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#6 0x5578998645d4 in _start (/src/soloud/harness+0x395d4) (BuildId: 564525bdfb4ff8144e0982209d7e978677d8be1c)
SUMMARY: AddressSanitizer: heap-buffer-overflow /src/soloud/src/audiosource/wav/soloud_wav.cpp:257:38 in SoLoud::Wav::loadflac(SoLoud::MemoryFile*)
Shadow bytes around the buggy address:
0x7fd35c8f6980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x7fd35c8f6c00:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7fd35c8f6e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==63267==ABORTING
Segmentation Fault (Write) in SoLoud::Wav::loadwav at soloud_wav.cpp:126
Description
The crash occurs within SoLoud::Wav::loadwav at src/audiosource/wav/soloud_wav.cpp:126:38, which is invoked via loadMem. The AddressSanitizer report indicates an invalid WRITE memory access to an unknown address (0x7f6e9ae87400), likely caused by a crafted WAV file processing.
Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
Vulnerability Details
- Type: Segmentation Fault (SEGV)
- Access Type: WRITE
- Location: src/audiosource/wav/soloud_wav.cpp:126:38
- Function: SoLoud::Wav::loadwav
Reproduce
- Build soloud and harness with Release optimization and ASAN enabled.
harness.cpp
#include "soloud.h"
#include "soloud_wav.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
if (argc < 2) {
return 1;
}
FILE *f = fopen(argv[1], "rb");
if (!f) {
return 1;
}
fseek(f, 0, SEEK_END);
long len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
if (!buf) {
fclose(f);
return 1;
}
if (fread(buf, 1, len, f) != (size_t)len) {
free(buf);
fclose(f);
return 1;
}
fclose(f);
SoLoud::Soloud soloud;
soloud.init(SoLoud::Soloud::CLIP_ROUNDOFF | SoLoud::Soloud::ENABLE_VISUALIZATION,
SoLoud::Soloud::NULLDRIVER);
SoLoud::Wav wav;
int res = wav.loadMem(buf, len, false, false);
if (res == 0) {
SoLoud::handle h = soloud.play(wav);
soloud.stop(h);
}
soloud.deinit();
free(buf);
return 0;
}
- Run with the crashing file:
./harness repro
ASAN report
AddressSanitizer:DEADLYSIGNAL
=================================================================
==13495==ERROR: AddressSanitizer: SEGV on unknown address 0x7f6e9ae87400 (pc 0x561a743ff86b bp 0x7fff778b43f0 sp 0x7fff778b4300 T0)
==13495==The signal is caused by a WRITE memory access.
#0 0x561a743ff86b in SoLoud::Wav::loadwav(SoLoud::MemoryFile*) /src/soloud/src/audiosource/wav/soloud_wav.cpp:126:38
#1 0x561a744025d4 in SoLoud::Wav::loadMem(unsigned char const*, unsigned int, bool, bool) /src/soloud/src/audiosource/wav/soloud_wav.cpp:314:10
#2 0x561a743a6124 in main /src/soloud/harness.cpp:39:19
#3 0x7f6d81dc01c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#4 0x7f6d81dc028a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#5 0x561a742c25d4 in _start (/src/soloud/harness+0x395d4) (BuildId: 564525bdfb4ff8144e0982209d7e978677d8be1c)
==13495==Register values:
rax = 0x00007f6e9ae87400 rbx = 0x00007fff778b4300 rcx = 0x0000000000000005 rdx = 0x00007f6ce1c2b800
rdi = 0x00007f6d809001f4 rsi = 0x000000006e496f00 rbp = 0x00007fff778b43f0 rsp = 0x00007fff778b4300
r8 = 0x0000000000000000 r9 = 0x000000006e496f00 r10 = 0x00007f6d809001f0 r11 = 0x00007f6d809001f4
r12 = 0x0000000000000001 r13 = 0x0000000000000000 r14 = 0x0000561a745872a0 r15 = 0x0000000000000001
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /src/soloud/src/audiosource/wav/soloud_wav.cpp:126:38 in SoLoud::Wav::loadwav(SoLoud::MemoryFile*)
==13495==ABORTING
Global-buffer-overflow (Read) in drwav_read_pcm_frames_s16__msadpcm (dr_wav.h)
Description
The crash occurs within drwav_read_pcm_frames_s16__msadpcm, which is invoked via SoLoud::Wav::loadMem. The AddressSanitizer report indicates an invalid READ memory access of size 4 on a global buffer.
Environment
- OS: Linux x86_64
- Complier: Clang
- Build Configuration: Release mode with ASan enabled.
Vulnerability Details
- Type: Global-buffer-overflow (Read)
- Location: src/audiosource/wav/dr_wav.h (inside drwav_read_pcm_frames_s16__msadpcm)
- Context: The issue is triggered when parsing a crafted WAV file (MSADPCM format). The invalid read occurs 4 bytes before the global variable g_drwavAlawTable.
Reproduce
- Build soloud and harness with Release optimization and ASAN enabled.
harness.cpp
#include "soloud.h"
#include "soloud_wav.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
if (argc < 2) {
return 1;
}
FILE *f = fopen(argv[1], "rb");
if (!f) {
return 1;
}
fseek(f, 0, SEEK_END);
long len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
if (!buf) {
fclose(f);
return 1;
}
if (fread(buf, 1, len, f) != (size_t)len) {
free(buf);
fclose(f);
return 1;
}
fclose(f);
SoLoud::Soloud soloud;
soloud.init(SoLoud::Soloud::CLIP_ROUNDOFF | SoLoud::Soloud::ENABLE_VISUALIZATION,
SoLoud::Soloud::NULLDRIVER);
SoLoud::Wav wav;
int res = wav.loadMem(buf, len, false, false);
if (res == 0) {
SoLoud::handle h = soloud.play(wav);
soloud.stop(h);
}
soloud.deinit();
free(buf);
return 0;
}
- Run with the crashing file:
./harness repro
ASAN report
==56122==ERROR: AddressSanitizer: global-buffer-overflow on address 0x55b60ae9589c at pc 0x55b60ad857f9 bp 0x7fff0ab51570 sp 0x7fff0ab51568
READ of size 4 at 0x55b60ae9589c thread T0
#0 0x55b60ad857f8 in drwav_read_pcm_frames_s16__msadpcm(drwav*, unsigned long long, short*) /src/soloud/src/audiosource/wav/dr_wav.h
#1 0x55b60ad8a29b in drwav_read_pcm_frames_s16 /src/soloud/src/audiosource/wav/dr_wav.h:6157:16
#2 0x55b60ad910db in drwav_read_pcm_frames_f32__msadpcm(drwav*, unsigned long long, float*) /src/soloud/src/audiosource/wav/dr_wav.h:6376:35
#3 0x55b60ad910db in drwav_read_pcm_frames_f32 /src/soloud/src/audiosource/wav/dr_wav.h:6526:16
#4 0x55b60ad4a6b2 in SoLoud::Wav::loadwav(SoLoud::MemoryFile*) /src/soloud/src/audiosource/wav/soloud_wav.cpp:121:4
#5 0x55b60ad4d5d4 in SoLoud::Wav::loadMem(unsigned char const*, unsigned int, bool, bool) /src/soloud/src/audiosource/wav/soloud_wav.cpp:314:10
#6 0x55b60acf1124 in main /src/soloud/harness.cpp:39:19
#7 0x7f669f5e51c9 (/lib/x86_64-linux-gnu/libc.so.6+0x2a1c9) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#8 0x7f669f5e528a in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28a) (BuildId: 274eec488d230825a136fa9c4d85370fed7a0a5e)
#9 0x55b60ac0d5d4 in _start (/src/soloud/harness+0x395d4) (BuildId: 564525bdfb4ff8144e0982209d7e978677d8be1c)
0x55b60ae9589c is located 4 bytes before global variable '__PRETTY_FUNCTION__._ZL30drwav_read_pcm_frames_s16__imaP5drwavyPs' defined in '/src/soloud/src/audiosource/wav/dr_wav.h:5737' (0x55b60ae958a0) of size 82
'__PRETTY_FUNCTION__._ZL30drwav_read_pcm_frames_s16__imaP5drwavyPs' is ascii string 'drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav *, drwav_uint64, drwav_int16 *)'
0x55b60ae9589c is located 88 bytes after global variable 'drwav_read_pcm_frames_s16__ima(drwav*, unsigned long long, short*)::stepTable' defined in '/src/soloud/src/audiosource/wav/dr_wav.h:5725' (0x55b60ae956e0) of size 356
SUMMARY: AddressSanitizer: global-buffer-overflow /src/soloud/src/audiosource/wav/dr_wav.h in drwav_read_pcm_frames_s16__msadpcm(drwav*, unsigned long long, short*)
Shadow bytes around the buggy address:
0x55b60ae95600: 00 00 00 04 f9 f9 f9 f9 00 00 00 04 f9 f9 f9 f9
0x55b60ae95680: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00
0x55b60ae95700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55b60ae95780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55b60ae95800: 00 00 00 00 00 00 00 00 04 f9 f9 f9 f9 f9 f9 f9
=>0x55b60ae95880: f9 f9 f9[f9]00 00 00 00 00 00 00 00 00 00 02 f9
0x55b60ae95900: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
0x55b60ae95980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55b60ae95a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55b60ae95a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x55b60ae95b00: 00 00 00 00 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==56122==ABORTING
Please let me know if you need any further information.
Best regards.