Skip to content

Heap OOB read in File_Aac::Streams_Finish from uninitialized num_window_groups #2625

Description

@mega-wli

Summary

File_Aac::File_Aac() leaves num_window_groups, num_sec[8], and sect_cb[8][64] uninitialized. Streams_Finish() (File_Aac.cpp:199, v25.10) then unconditionally runs:

void File_Aac::Streams_Finish()
{
    std::bitset<32> sect_cb_used;
    for (int g = 0; g < num_window_groups; g++)
    {
        for (int8u i = 0; i < num_sec[g]; i++)
        {
            if (sect_cb[g][i] == 13) //NOISE_HCB
            {
                Fill(Stream_Audio, 0, Audio_Format_Settings, "PNS");
                break;
            }
        }
    }
    ...
}

If teardown reaches that loop before any channel element's ics_info() / section_data() parse has written those members, the loop walks past the fixed-size array bounds with garbage indices.

The trigger we hit in production is the buffer API (Open_Buffer_Init/_Continue/_Finalize) supplied with only a bounded prefix of an MP4-with-AAC file — a documented usage pattern for metadata extraction without fetching the full asset. A locally-truncated AAC file, or any early parse abort, reaches the same teardown state.

Affected

Versions 25.09 and later, including current master. The Streams_Finish loop that performs the OOB read was introduced in commit 385db6a7, first shipped in v25.09. The three members have always been uninitialized in the constructor, but earlier versions have no loop to read them. Line numbers below are from v25.10.

Production crash backtrace

Captured from a release build linked against libmediainfo v25.10; all file/line pairs in the frames below are v25.10 line numbers.

Crashed: Thread: SIGSEGV  0x0000007870e00000
#00 pc 0x2076018 (MediaInfoLib::File_Aac::Streams_Finish() [File_Aac.cpp:206])
#01 pc 0x2076068 (MediaInfoLib::File_Aac::Streams_Finish() [File__Analyze_MinimizeSize.h:1064])
#02 pc 0x1ff93cc (MediaInfoLib::File__Analyze::ForceFinish() [File__Analyze.cpp:3648])
#03 pc 0x21d326c (MediaInfoLib::File_Mpeg4::Streams_Finish() [File_Mpeg4.cpp:988])
#04 pc 0x1ff93cc (MediaInfoLib::File__Analyze::ForceFinish() [File__Analyze.cpp:3648])
#05 pc 0x1ffac9c (MediaInfoLib::File__Analyze::Open_Buffer_Finalize(bool) [File__Analyze.cpp:1719])
#06 pc 0x206cbd8 (MediaInfoLib::MediaInfo_Internal::Open_Buffer_Finalize() [MediaInfo_Internal.cpp:1813])

Frame 00 is the sect_cb[g][i] access at File_Aac.cpp:206. The page-aligned fault address (...e00000) suggests the OOB read landed in an unmapped page; visible crashes in plain release builds are rare for that reason — usually the read lands in an adjacent live heap allocation and silently returns garbage. A sanitizer build is the most reliable way to reproduce.

Proposed fix

Zero-initialize num_window_groups in the constructor; the loop then short-circuits when section-data was never parsed, which matches the loop's intent.

--- a/Source/MediaInfo/Audio/File_Aac.cpp
+++ b/Source/MediaInfo/Audio/File_Aac.cpp
@@ -104,6 +104,7 @@ File_Aac::File_Aac()
 
     //Temp
     CanFill=true;
+    num_window_groups=0;
 }

We have applied this in our build and the crash no longer reproduces. Happy to send a PR if useful.

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