Xiph: bound comment field lengths (#1424)

Xiph comment lengths are read from the file. Without checking them
against the remaining packet, a wrapped length can reset the parser
position and make each field iteration copy the same payload.
Reject truncated vendor and field data before advancing the parser.
This commit is contained in:
Acts1631
2026-08-18 07:07:33 +02:00
committed by GitHub
parent 7f2964ab8b
commit 0a13a11bad
+20 -5
View File
@@ -427,14 +427,28 @@ void Ogg::XiphComment::parse(const ByteVector &data)
// The first thing in the comment data is the vendor ID length, followed by a
// UTF8 string with the vendor ID.
if(data.size() < 8) {
debug("Ogg::XiphComment::parse() - Comment data is too short.");
return;
}
unsigned int pos = 0;
const unsigned int vendorLength = data.toUInt(0, false);
pos += 4;
if(vendorLength > data.size() - pos) {
debug("Ogg::XiphComment::parse() - Vendor ID exceeds comment data.");
return;
}
d->vendorID = String(data.mid(pos, vendorLength), String::UTF8);
pos += vendorLength;
if(data.size() - pos < 4) {
debug("Ogg::XiphComment::parse() - Missing comment field count.");
return;
}
// Next the number of fields in the comment vector.
const unsigned int commentFields = data.toUInt(pos, false);
@@ -451,17 +465,18 @@ void Ogg::XiphComment::parse(const ByteVector &data)
// Each comment field is in the format "KEY=value" in a UTF8 string and has
// 4 bytes before the text starts that gives the length.
if(data.size() - pos < 4)
break;
const unsigned int commentLength = data.toUInt(pos, false);
pos += 4;
if(commentLength > data.size() - pos)
break;
const ByteVector entry = data.mid(pos, commentLength);
pos += commentLength;
// Don't go past data end
if(pos > data.size())
break;
// Check for field separator
const int sep = entry.find('=');