diff --git a/taglib/matroska/ebml/ebmlmasterelement.cpp b/taglib/matroska/ebml/ebmlmasterelement.cpp index 22e5d9b7..56afc393 100644 --- a/taglib/matroska/ebml/ebmlmasterelement.cpp +++ b/taglib/matroska/ebml/ebmlmasterelement.cpp @@ -21,6 +21,7 @@ #include "ebmlmasterelement.h" #include "ebmlvoidelement.h" #include "ebmlutils.h" +#include "tdebug.h" #include "tfile.h" using namespace TagLib; @@ -97,18 +98,34 @@ void EBML::MasterElement::setMinRenderSize(offset_t minimumSize) minRenderSize = minimumSize; } -bool EBML::MasterElement::read(File &file) +bool EBML::MasterElement::read(File &file, int depth) { + static constexpr int MAX_EBML_DEPTH = 64; + if(depth > MAX_EBML_DEPTH) { + debug("EBML: Maximum nesting depth exceeded"); + return false; + } const offset_t maxOffset = file.tell() + dataSize; std::unique_ptr element; while((element = findNextElement(file, maxOffset))) { - if(!element->read(file)) - return false; + if(auto master = dynamic_cast(element.get())) { + if(!master->read(file, depth + 1)) + return false; + } + else { + if(!element->read(file)) + return false; + } elements.push_back(std::move(element)); } return file.tell() == maxOffset; } +bool EBML::MasterElement::read(File &file) +{ + return read(file, 0); +} + ByteVector EBML::MasterElement::render() { ByteVector buffer = renderId(); diff --git a/taglib/matroska/ebml/ebmlmasterelement.h b/taglib/matroska/ebml/ebmlmasterelement.h index 52cfe526..3b77094a 100644 --- a/taglib/matroska/ebml/ebmlmasterelement.h +++ b/taglib/matroska/ebml/ebmlmasterelement.h @@ -55,6 +55,8 @@ namespace TagLib void setMinRenderSize(offset_t minimumSize); protected: + bool read(File &file, int depth); + offset_t offset; offset_t padding = 0; offset_t minRenderSize = 0; diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp index 78c96a93..935b3fb7 100644 --- a/taglib/mp4/mp4atom.cpp +++ b/taglib/mp4/mp4atom.cpp @@ -51,7 +51,7 @@ public: AtomList children; }; -MP4::Atom::Atom(File *file) +MP4::Atom::Atom(File *file, int depth) : d(std::make_unique(file->tell())) { d->children.setAutoDelete(true); @@ -109,8 +109,13 @@ MP4::Atom::Atom(File *file) else if(d->name == "stsd") { file->seek(8, File::Current); } + static constexpr int MAX_MP4_ATOM_DEPTH = 64; + if(depth > MAX_MP4_ATOM_DEPTH) { + debug("MP4: Maximum nesting depth exceeded"); + return; + } while(file->tell() < d->offset + d->length) { - auto child = new MP4::Atom(file); + auto child = new MP4::Atom(file, depth + 1); d->children.append(child); if(child->d->length == 0) return; @@ -122,6 +127,11 @@ MP4::Atom::Atom(File *file) file->seek(d->offset + d->length); } +MP4::Atom::Atom(File *file) + : Atom(file, 0) +{ +} + MP4::Atom::~Atom() = default; MP4::Atom * diff --git a/taglib/mp4/mp4atom.h b/taglib/mp4/mp4atom.h index 58e13a3b..1776ba90 100644 --- a/taglib/mp4/mp4atom.h +++ b/taglib/mp4/mp4atom.h @@ -89,6 +89,9 @@ namespace TagLib { const ByteVector &name() const; const AtomList &children() const; + protected: + Atom(File *file, int depth); + private: class AtomPrivate; TAGLIB_MSVC_SUPPRESS_WARNING_NEEDS_TO_HAVE_DLL_INTERFACE