mirror of
https://github.com/taglib/taglib.git
synced 2026-10-09 09:42:03 -04:00
Bound text value counts in ID3v2 and APE tags (#1458)
Null-separated text values create a ByteVector and String for each tiny field. A 1 MB tag can allocate over 100 MB and abort memory-limited applications. Limit decoded values based on input size and stop before creating String objects when the value count exceeds the budget.
This commit is contained in:
+15
-2
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "apeitem.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <numeric>
|
||||
|
||||
@@ -232,8 +233,20 @@ void APE::Item::parse(const ByteVector &data)
|
||||
setReadOnly(flags & 1);
|
||||
setType(static_cast<ItemTypes>((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<int>(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;
|
||||
}
|
||||
|
||||
@@ -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<unsigned int>(dataLength) / 32));
|
||||
const ByteVectorList l = ByteVectorList::split(
|
||||
data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign,
|
||||
static_cast<int>(maxFields + 1));
|
||||
if(l.size() > maxFields) {
|
||||
debug("ID3v2: Maximum text field count exceeded");
|
||||
return;
|
||||
}
|
||||
|
||||
d->fieldList.clear();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user