Skip to content

Memory leak in header parsing via _vorbis_unpack_comment during multi-stream file open #125

Description

@OwenSanzas

Summary

When opening a crafted multi-stream Ogg Vorbis file, ov_open_callbacks() leaks ~105KB of memory. The _open_seekable2 / _bisect_forward_serialno path allocates memory during header parsing via _vorbis_unpack_comment() but fails to free it when the open operation fails. Repeated processing of such files causes resource exhaustion.

Root Cause

_vorbis_unpack_comment() in info.c allocates memory for comments during header parsing. When ov_open_callbacks() fails during the _open_seekable2 path for multi-stream files, these allocations are not freed. ov_clear() does not clean up intermediate stream allocations made during _bisect_forward_serialno().

Reproduction

A standalone metadata reader application using only public libvorbisfile API (ov_open_callbacks(), ov_info(), ov_comment()) triggers the leak. No fuzzer harness is required.

Build with AddressSanitizer + LeakSanitizer:

clang -fsanitize=address -g -O1 vorbis_info_reader.c -lvorbisfile -lvorbis -logg -lm -o vorbis_info_reader
ASAN_OPTIONS=detect_leaks=1 ./vorbis_info_reader crafted.ogg

Sanitizer Output

=================================================================
==PID==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 5784 byte(s) in 1 object(s) allocated from:
    #0 in calloc
    #1 in vorbis_info_init lib/info.c:155:19
    #2 in _bisect_forward_serialno lib/vorbisfile.c:571:9
    #3 in _open_seekable2 lib/vorbisfile.c:647:6
    #4 in _ov_open2 lib/vorbisfile.c:943:13
    #5 in ov_open_callbacks lib/vorbisfile.c:999:10
    #6 in main vorbis_info_reader.c:152:11

Direct leak of 46 byte(s) in 1 object(s) allocated from:
    #0 in calloc
    #1 in _vorbis_unpack_comment lib/info.c:248:14
    #2 in _fetch_headers lib/vorbisfile.c:377:17
    #3 in _bisect_forward_serialno lib/vorbisfile.c:571:9

[... additional leak traces from vorbis_staticbook_unpack, mapping0_unpack, floor1_unpack ...]

SUMMARY: AddressSanitizer: 104670 byte(s) leaked in 312 allocation(s).

Suggested Fix

In vorbisfile.c, ensure that intermediate vorbis_info and vorbis_comment allocations made during _bisect_forward_serialno() are properly freed on error paths in _open_seekable2(). Add cleanup calls to vorbis_info_clear() and vorbis_comment_clear() for each intermediate stream's info/comment when ov_open_callbacks() fails.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions