mirror of
https://github.com/taglib/taglib.git
synced 2026-04-12 17:09:50 -04:00
Fix unbounded recursion in EBML/Matroska MasterElement and MP4 atoms (#1326)
Credits for fix and reporting go to https://github.com/ericliu-12.
This commit is contained in:
@ -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> element;
|
||||
while((element = findNextElement(file, maxOffset))) {
|
||||
if(!element->read(file))
|
||||
return false;
|
||||
if(auto master = dynamic_cast<MasterElement *>(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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -51,7 +51,7 @@ public:
|
||||
AtomList children;
|
||||
};
|
||||
|
||||
MP4::Atom::Atom(File *file)
|
||||
MP4::Atom::Atom(File *file, int depth)
|
||||
: d(std::make_unique<AtomPrivate>(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 *
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user