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.
Summary
File_Aac::File_Aac()leavesnum_window_groups,num_sec[8], andsect_cb[8][64]uninitialized.Streams_Finish()(File_Aac.cpp:199, v25.10) then unconditionally runs: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. TheStreams_Finishloop that performs the OOB read was introduced in commit385db6a7, 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.
Frame 00 is the
sect_cb[g][i]access atFile_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_groupsin the constructor; the loop then short-circuits when section-data was never parsed, which matches the loop's intent.We have applied this in our build and the crash no longer reproduces. Happy to send a PR if useful.