diff --git a/taglib/ape/apeitem.cpp b/taglib/ape/apeitem.cpp index a5c8099e..83618500 100644 --- a/taglib/ape/apeitem.cpp +++ b/taglib/ape/apeitem.cpp @@ -25,6 +25,7 @@ #include "apeitem.h" +#include #include #include @@ -232,8 +233,20 @@ void APE::Item::parse(const ByteVector &data) setReadOnly(flags & 1); setType(static_cast((flags >> 1) & 3)); - if(Text == d->type) - d->text = StringList(ByteVectorList::split(val, '\0'), String::UTF8); + if(Text == d->type) { + // Short, null-separated values otherwise allocate far more memory than + // the item occupies on disk. + static constexpr unsigned int MAX_TEXT_VALUE_COUNT = 50000; + const unsigned int maxValues = std::min(MAX_TEXT_VALUE_COUNT, + std::max(1024U, val.size() / 32)); + const ByteVectorList values = ByteVectorList::split( + val, '\0', 1, static_cast(maxValues + 1)); + if(values.size() > maxValues) { + debug("APE::Item::parse() -- Maximum text value count exceeded"); + return; + } + d->text = StringList(values, String::UTF8); + } else d->value = val; } diff --git a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp index 4406eaa5..9715ac9f 100644 --- a/taglib/mpeg/id3v2/frames/textidentificationframe.cpp +++ b/taglib/mpeg/id3v2/frames/textidentificationframe.cpp @@ -31,6 +31,7 @@ #include "tutils.h" #include "tpropertymap.h" +#include "tdebug.h" #include "id3v1genres.h" #include "id3v2tag.h" @@ -236,7 +237,18 @@ void TextIdentificationFrame::parseFields(const ByteVector &data) while(dataLength % byteAlign != 0) dataLength++; - const ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign); + // Short, null-separated values otherwise allocate far more memory than the + // frame occupies on disk. Allow at least 1024 fields in small frames. + static constexpr unsigned int MAX_TEXT_FIELD_COUNT = 50000; + const unsigned int maxFields = std::min(MAX_TEXT_FIELD_COUNT, + std::max(1024U, static_cast(dataLength) / 32)); + const ByteVectorList l = ByteVectorList::split( + data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign, + static_cast(maxFields + 1)); + if(l.size() > maxFields) { + debug("ID3v2: Maximum text field count exceeded"); + return; + } d->fieldList.clear();