mirror of
https://github.com/taglib/taglib.git
synced 2026-08-14 06:17:00 -04:00
Fix Shorten AIFF chunk offset wrap (#1381)
A crafted embedded AIFF chunk size could wrap the parser offset and make it repeatedly process the same chunk, causing a denial of service. Validate AIFF chunk headers and padded sizes against the remaining verbatim-header data, and advance every parsed chunk to its checked end.
This commit is contained in:
@@ -471,14 +471,27 @@ void Shorten::File::read(AudioProperties::ReadStyle propertiesStyle)
|
||||
|
||||
auto sawCommonChunk = false;
|
||||
while(offset < chunkData.size()) {
|
||||
if(chunkData.size() - offset < 8) {
|
||||
debug("Shorten::File::read() -- Truncated AIFF chunk header.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
chunkID = chunkData.toUInt(offset, true);
|
||||
offset += 4;
|
||||
|
||||
auto chunkSize = chunkData.toUInt(offset, true);
|
||||
const auto chunkSize = chunkData.toUInt(offset, true);
|
||||
offset += 4;
|
||||
|
||||
// All chunks must have an even length but the pad byte is not included in chunkSize
|
||||
chunkSize += (chunkSize & 1);
|
||||
const uint64_t paddedChunkSize = static_cast<uint64_t>(chunkSize) + (chunkSize & 1);
|
||||
if(paddedChunkSize > chunkData.size() - offset) {
|
||||
debug("Shorten::File::read() -- AIFF chunk exceeds verbatim header.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int chunkEnd = offset + static_cast<unsigned int>(paddedChunkSize);
|
||||
|
||||
switch(chunkID) {
|
||||
case 0x434f4d4d /*'COMM'*/:
|
||||
@@ -523,11 +536,11 @@ void Shorten::File::read(AudioProperties::ReadStyle propertiesStyle)
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip all other chunks
|
||||
default:
|
||||
offset += chunkSize;
|
||||
break;
|
||||
}
|
||||
|
||||
offset = chunkEnd;
|
||||
}
|
||||
|
||||
if(!sawCommonChunk) {
|
||||
|
||||
Reference in New Issue
Block a user