Memory Leak in ogg123
Hi, we have found memory leak in ogg123 and would like to report this issue. Could you confirm whether this is a bug? I am happy to provide any additional information needed.
Summary
The ogg123 application contains a memory leak bug where driver-specific options allocated via ao_append_options()
are never properly freed, violating libao's documented usage patterns.
CWE Classification: CWE-401 - Missing Release of Memory after Effective Lifetime
Component: ogg123 (vorbis-tools)
Vorbis-tools Version: 1.4.3
Test Environment
- Operating System: Ubuntu 22.04 LTS
- Architecture: x86_64
- Compiler: clang with AddressSanitizer (clang version: 14.0.0)
Reproduction Steps
# Obtain the source code
wget -O- https://github.com/xiph/vorbis-tools/archive/refs/tags/v1.4.3.tar.gz | tar zxv
# Obtain an argument that cause a crash
git clone https://github.com/momo-trip/poc_ogg123.git
cp poc_ogg123/input vorbis-tools-1.4.3/input
# Setup
cd vorbis-tools-1.4.3
cat > build.sh << 'EOF'
#!/bin/bash
./autogen.sh
./configure CC=clang CXX=clang++ \
CFLAGS="-fsanitize=address -g -O1" \
CXXFLAGS="-fsanitize=address -g -O1" \
LDFLAGS="-fsanitize=address"
make
EOF
# Compile with AddressSanitizer
chmod +x build.sh
./build.sh
# Execute
cat input | xargs ./ogg123/ogg123
Output
--- Cannot open playlist file /b. Skipped.
./ogg123/ogg123: invalid option -- '&'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'G'
./ogg123/ogg123: invalid option -- 'S'
./ogg123/ogg123: invalid option -- ':'
./ogg123/ogg123: invalid option -- ':'
./ogg123/ogg123: invalid option -- '-'
./ogg123/ogg123: invalid option -- '-'
./ogg123/ogg123: invalid option -- '4'
./ogg123/ogg123: invalid option -- 'a'
./ogg123/ogg123: invalid option -- '-'
./ogg123/ogg123: invalid option -- 'a'
--- Cannot play every chunk 0 times.
--- To do a test decode, use the null output driver.
./ogg123/ogg123: option requires an argument -- 'd'
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Audio Device: Null output
Author: Stan Seibert <volsung@asu.edu>
Comments: This driver does nothing.
Cannot open a.
Cannot open |dll.
Cannot open .
Cannot open |d.
Cannot open .
Cannot open /--a.
Cannot open null.
Cannot open tlell.
Cannot open u}l.
Cannot open t.
Cannot open lell.
Cannot open 2l.
Cannot open t.
Cannot open l.
Cannot open t.
Cannot open $TMPnull.
Cannot open nval.
Cannot open 64.
Cannot open puuo�-a.
Cannot open te.
Cannot open ull.
Cannot open t.
Cannot open t.
Cannot open l.
Cannot open t.
=================================================================
==550749==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 168 byte(s) in 7 object(s) allocated from:
#0 0x55d0bea028b8 in __interceptor_calloc (/home/ubuntu/poc/vorbis-tools-1.4.3/ogg123/ogg123+0xae8b8) (BuildId: 91d126346120c2b1aa21947589c92eaa267877ed)
#1 0x78e0eeb75c05 in ao_append_option (/lib/x86_64-linux-gnu/libao.so.4+0x3c05) (BuildId: c1fb0d7f21fbf8c6ab00e445b1bd8d9f1ccd3857)
Indirect leak of 56 byte(s) in 7 object(s) allocated from:
#0 0x55d0be9ed0d3 in strdup (/home/ubuntu/poc/vorbis-tools-1.4.3/ogg123/ogg123+0x990d3) (BuildId: 91d126346120c2b1aa21947589c92eaa267877ed)
#1 0x78e0eeb75c15 in ao_append_option (/lib/x86_64-linux-gnu/libao.so.4+0x3c15) (BuildId: c1fb0d7f21fbf8c6ab00e445b1bd8d9f1ccd3857)
Indirect leak of 7 byte(s) in 7 object(s) allocated from:
#0 0x55d0be9ed0d3 in strdup (/home/ubuntu/poc/vorbis-tools-1.4.3/ogg123/ogg123+0x990d3) (BuildId: 91d126346120c2b1aa21947589c92eaa267877ed)
#1 0x78e0eeb75c2e in ao_append_option (/lib/x86_64-linux-gnu/libao.so.4+0x3c2e) (BuildId: c1fb0d7f21fbf8c6ab00e445b1bd8d9f1ccd3857)
SUMMARY: AddressSanitizer: 231 byte(s) leaked in 21 allocation(s).
Root cause
The issue stems from non-compliance with libao's documented driver-specific options handling pattern as described in https://github.com/xiph/libao/blob/20dc8ed9fa4605f5c25e7496ede42e8ba6468225/doc/overview.html#L57-L74.
ogg123 uses a custom global ogg123_options_t options
structure (https://github.com/xiph/vorbis-tools/blob/0b3fbf42eb3897d32f4a75baa2dc915a4ca45e8e/ogg123/ogg123.c#L65C1-L65C26) instead of following libao's standard approach. Because this global options structure is separate from libao's lifecycle management, it is not subject to the cleanup handled by ao_initialize
(https://github.com/xiph/vorbis-tools/blob/0b3fbf42eb3897d32f4a75baa2dc915a4ca45e8e/ogg123/ogg123.c#L403) and ao_shutdown
(https://github.com/xiph/vorbis-tools/blob/0b3fbf42eb3897d32f4a75baa2dc915a4ca45e8e/ogg123/audio.c#L126).
Consequently, ao_free_options()
cleanup is never performed on the ogg123_options_t options
structure. When -q
or -v
options are processed, ao_append_options
calls strdup()
internally to allocate memory chunks that are never freed, resulting in a memory leak.