Memory leak in aubio_source_avcodec_reset_resampler when swr_init fails on malformed audio
Summary
When opening a malformed or crafted audio file via new_aubio_source (using the libavcodec backend), aubio_source_avcodec_reset_resampler allocates a SwrContext via swr_alloc() but fails to free it when swr_init() subsequently fails. This results in a confirmed 86,024-byte definite memory leak on every failed open attempt.
The bug is reproducible on an unmodified upstream build using the standard aubioquiet, aubionotes, and aubiopitch CLI tools — no fuzzer harness required.
Affected File
src/io/source_avcodec.c — aubio_source_avcodec_reset_resampler(), lines ~338–384
Root Cause
In aubio_source_avcodec_reset_resampler:
void aubio_source_avcodec_reset_resampler(aubio_source_avcodec_t * s)
{
if ( s->avr == NULL ) {
int err;
SwrContext *avr = swr_alloc(); // <-- allocated here
// ... av_opt_set_* calls ...
if ( ( err = swr_init(avr) ) < 0)
{
char errorstr[256];
av_strerror (err, errorstr, sizeof(errorstr));
AUBIO_ERR("source_avcodec: Could not open resampling context"
" for %s (%s)\n", s->path, errorstr);
return; // <-- BUG: returns without calling swr_free(&avr)
}
s->avr = avr;
}
}
When swr_init(avr) fails (e.g. due to an invalid channel layout in a malformed file), the local avr pointer is never assigned to s->avr, so the subsequent del_aubio_source_avcodec → aubio_source_avcodec_close cleanup path never reaches it. The SwrContext is leaked.
Steps to Reproduce
Using a malformed WAV file that causes an invalid channel layout (e.g. "257 channels"), run:
LD_LIBRARY_PATH=./build/src valgrind --leak-check=full --track-origins=yes \
build/examples/aubioquiet -i <malformed_audio_file>
The malformed file can be obtained via AFL++ fuzzing of new_aubio_source, or crafted by hand to contain an invalid channel count in the WAV/libav stream headers.
Observed Output
AUBIO error (expected):
[SWR @ ...] Input channel layout "257 channels" is invalid or unsupported.
AUBIO ERROR: source_avcodec: Could not open resampling context for <file> (Invalid argument)
Valgrind output (definite leak):
==34249== 86,024 bytes in 1 blocks are definitely lost in loss record 274 of 274
==34249== at 0x484E366: posix_memalign (vgpreload_memcheck-amd64-linux.so)
==34249== by 0x65E7C14: av_malloc (libavutil.so.58.29.100)
==34249== by 0x65E7F80: av_mallocz (libavutil.so.58.29.100)
==34249== by 0x656A5F4: swr_alloc (libswresample.so.4.12.100)
==34249== by 0x486CA0F: aubio_source_avcodec_reset_resampler.part.0 (source_avcodec.c:343)
==34249== by 0x486D701: new_aubio_source_avcodec (source_avcodec.c:321)
==34249== by 0x486C846: new_aubio_source (source.c:62)
==34249== by 0x109CBC: examples_common_init (utils.c:101)
==34249== by 0x10934E: main (aubioquiet.c:54)
==34249==
==34249== LEAK SUMMARY:
==34249== definitely lost: 86,024 bytes in 1 blocks
Also confirmed via AddressSanitizer LeakSanitizer on an ASAN build:
==29777==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 86024 byte(s) in 1 object(s) allocated from:
#0 ... posix_memalign
#1 ... av_malloc (libavutil.so.58)
SUMMARY: AddressSanitizer: 86024 byte(s) leaked in 1 allocation(s).
A second leak is also present (crash file id:000001)
Running a second malformed file (crafted G726 ADPCM with invalid codec parameters) produces two definite leaks:
==37152== definitely lost: 1,560 bytes in 2 blocks
==37152== indirectly lost: 35,794 bytes in 16 blocks
These trace back to:
avcodec_alloc_context3 at source_avcodec.c:233 — codec context not freed on the Could not load codec error path
avformat_open_input at source_avcodec.c:176 — format context not freed in some error paths
Environment
- aubio: latest upstream
master (fresh build, unmodified)
- libavcodec: 60.31.102
- libavutil: 58.29.100
- libswresample: 4.12.100
- Valgrind: 3.22.0
- OS: Ubuntu 24, x86_64
Memory leak in
aubio_source_avcodec_reset_resamplerwhenswr_initfails on malformed audioSummary
When opening a malformed or crafted audio file via
new_aubio_source(using the libavcodec backend),aubio_source_avcodec_reset_resamplerallocates aSwrContextviaswr_alloc()but fails to free it whenswr_init()subsequently fails. This results in a confirmed 86,024-byte definite memory leak on every failed open attempt.The bug is reproducible on an unmodified upstream build using the standard aubioquiet, aubionotes, and aubiopitch CLI tools — no fuzzer harness required.
Affected File
src/io/source_avcodec.c—aubio_source_avcodec_reset_resampler(), lines ~338–384Root Cause
In
aubio_source_avcodec_reset_resampler:When
swr_init(avr)fails (e.g. due to an invalid channel layout in a malformed file), the localavrpointer is never assigned tos->avr, so the subsequentdel_aubio_source_avcodec→aubio_source_avcodec_closecleanup path never reaches it. TheSwrContextis leaked.Steps to Reproduce
Using a malformed WAV file that causes an invalid channel layout (e.g. "257 channels"), run:
The malformed file can be obtained via AFL++ fuzzing of
new_aubio_source, or crafted by hand to contain an invalid channel count in the WAV/libav stream headers.Observed Output
AUBIO error (expected):
Valgrind output (definite leak):
Also confirmed via AddressSanitizer LeakSanitizer on an ASAN build:
A second leak is also present (crash file
id:000001)Running a second malformed file (crafted G726 ADPCM with invalid codec parameters) produces two definite leaks:
These trace back to:
avcodec_alloc_context3atsource_avcodec.c:233— codec context not freed on theCould not load codecerror pathavformat_open_inputatsource_avcodec.c:176— format context not freed in some error pathsEnvironment
master(fresh build, unmodified)