Resolve QuickTime chunk tables linearly (#1428)

A QuickTime chapter track can provide large stco and stsc
tables. QtChapterList::resolveSampleOffsets() currently walks every stsc
entry for every chunk, so a file with N entries can force O(N²) work during
MP4::File::qtChapters(). A 3.2 MB file with 200,000 entries took about 20
seconds in the release build.

Keep a cursor into stscEntries and advance it as chunk numbers
increase. This resolves the same ordered table in linear time while
avoiding attacker-controlled repeated scans.
This commit is contained in:
Acts1631
2026-08-21 05:59:27 +02:00
committed by GitHub
parent 0a3deeac75
commit d391029695
+5 -9
View File
@@ -943,19 +943,15 @@ namespace
std::vector<unsigned int> sampleOffsets;
const auto totalChunks = static_cast<unsigned int>(chunkOffsets.size());
unsigned int sampleIndex = 0;
std::size_t stscIndex = 0;
for(unsigned int chunkIdx = 0; chunkIdx < totalChunks; ++chunkIdx) {
// Find which stsc entry applies to this chunk (1-based)
const unsigned int chunkNum = chunkIdx + 1;
unsigned int samplesInChunk = stscEntries[0].samplesPerChunk;
for(const auto & stscEntry : stscEntries) {
if(stscEntry.firstChunk <= chunkNum) {
samplesInChunk = stscEntry.samplesPerChunk;
}
else {
break;
}
}
while(stscIndex + 1 < stscEntries.size() &&
stscEntries[stscIndex + 1].firstChunk <= chunkNum)
++stscIndex;
unsigned int samplesInChunk = stscEntries[stscIndex].samplesPerChunk;
unsigned int offsetInChunk = 0;
if(samplesInChunk > sizeInfo.sampleCount - sampleIndex)