From e589efd0dac005c45ff739a959463f3ecba2aa12 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Sat, 27 Jun 2026 07:09:33 +0200 Subject: [PATCH] Matroska: Fix crash when seek head invalid or missing (#1375) Also be more tolerant when parsing the seek head: - accept elements with offset 0, - skip invalid elements. --- taglib/matroska/ebml/ebmlmkseekhead.cpp | 11 ++++++----- taglib/matroska/ebml/ebmlmksegment.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/taglib/matroska/ebml/ebmlmkseekhead.cpp b/taglib/matroska/ebml/ebmlmkseekhead.cpp index c3d6ca8f..05ab579b 100644 --- a/taglib/matroska/ebml/ebmlmkseekhead.cpp +++ b/taglib/matroska/ebml/ebmlmkseekhead.cpp @@ -22,6 +22,8 @@ #include "matroskaseekhead.h" #include "ebmluintelement.h" #include "ebmlbinaryelement.h" +#include "tdebug.h" +#include "tutils.h" using namespace TagLib; @@ -51,21 +53,20 @@ std::unique_ptr EBML::MkSeekHead::parse(offset_t segmentData continue; const auto seekElement = element_cast(element); Matroska::Element::ID entryId = 0; - offset_t offset = 0; + offset_t offset = -1; for(const auto &seekElementChild : *seekElement) { if(const Id id = seekElementChild->getId(); id == Id::MkSeekID && !entryId) { if(auto data = element_cast(seekElementChild)->getValue(); data.size() == 4) entryId = data.toUInt(true); } - else if(id == Id::MkSeekPosition && !offset) + else if(id == Id::MkSeekPosition && offset < 0) offset = element_cast(seekElementChild)->getValue(); } - if(entryId && offset) + if(entryId && offset >= 0) seekHead->addEntry(entryId, offset); else { - seekHead.reset(); - return nullptr; + debug(Utils::formatString("Invalid seek element: ID=0x%x, offset=%lld", entryId, offset)); } } diff --git a/taglib/matroska/ebml/ebmlmksegment.cpp b/taglib/matroska/ebml/ebmlmksegment.cpp index 0fe72263..b9392938 100644 --- a/taglib/matroska/ebml/ebmlmksegment.cpp +++ b/taglib/matroska/ebml/ebmlmksegment.cpp @@ -125,7 +125,7 @@ bool EBML::MkSegment::readLimited(File &file, offset_t scanLimit) // Follow such MkSeekHead -> MkSeekHead chains so the real entries are // not silently dropped. List> entries = - matroskaSeekHead->entryList(); + matroskaSeekHead ? matroskaSeekHead->entryList() : List>(); // Guard against pathological / circular chains. int chainedSeekHeadsFollowed = 0; constexpr int MAX_CHAINED_SEEKHEADS = 8;