Skip to content

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

@OwenSanzas

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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions