Limit ID3 compressed-frame expansion (#1382)

A crafted compressed ID3v2 frame can declare an excessive output size
and cause zlib to allocate memory based on attacker-controlled data.

Bound decompression by an absolute 64 MiB limit and a 64:1 expansion
ratio, while retaining normal ID3v2.3 length handling.
This commit is contained in:
Acts1631
2026-08-01 06:18:24 +02:00
committed by GitHub
parent 3aa04e3be4
commit 18572e90a6
+14 -2
View File
@@ -27,6 +27,7 @@
#include <array>
#include <bitset>
#include <cstdint>
#include "tdebug.h"
#include "tstringlist.h"
@@ -57,6 +58,9 @@ public:
namespace
{
constexpr unsigned int maxCompressedFrameOutputSize = 64U * 1024U * 1024U;
constexpr unsigned int maxCompressedFrameRatio = 64;
bool isValidFrameID(const ByteVector &frameID)
{
if(frameID.size() != 4)
@@ -310,8 +314,16 @@ ByteVector Frame::fieldData(const ByteVector &frameData) const
return ByteVector();
}
const ByteVector outData = zlib::decompress(frameData.mid(frameDataOffset),
frameDataLength);
const ByteVector compressedData = frameData.mid(frameDataOffset);
const uint64_t maxOutputSizeForInput =
static_cast<uint64_t>(compressedData.size()) * maxCompressedFrameRatio;
if(frameDataLength > maxCompressedFrameOutputSize ||
frameDataLength > maxOutputSizeForInput) {
debug("Compressed frame exceeds decompression limit");
return ByteVector();
}
const ByteVector outData = zlib::decompress(compressedData, frameDataLength);
if(!outData.isEmpty() && frameDataLength != outData.size()) {
debug("frameDataLength does not match the data length returned by zlib");
}