Bug
readPictureBlock in vorbis.go reads a 4-byte dataLen from the input and passes it directly to make([]byte, dataLen) without any size cap:
// vorbis.go, line ~132
dataLen, err := readInt(r, 4)
if err != nil {
return err
}
data := make([]byte, dataLen)
A crafted FLAC file with dataLen = 0x7FFFFFFF causes a ~2 GB allocation from a 49-byte input. The allocation happens before io.ReadFull returns EOF, so the memory is committed regardless.
The rest of the codebase already has readBytesMaxUpfront (10 MB cap) in readBytes() / readString(), but this code path uses a raw make instead.
Reproduction
49-byte FLAC file (base64):
ZkxhQ4YAACkAAAADAAAACWltYWdlL3BuZwAAAAAAAAAAAAAAAAAAAAAAAAAAf////w==
Decode and run:
echo 'ZkxhQ4YAACkAAAADAAAACWltYWdlL3BuZwAAAAAAAAAAAAAAAAAAAAAAAAAAf////w==' | base64 -d > poc.bin
# Then in Go:
# tag.ReadFrom(bytes.NewReader(pocBytes))
# Observe ~2 GB allocation via runtime.ReadMemStats
Measured: TotalAlloc delta = 2147520480 bytes (2147.5 MB) from a 49-byte file. Tested on current HEAD (3d75831).
SHA-256 of poc.bin: 3ba94bb0597fa4689cad34e8f1e9866901cad38a64e80ab196504696322b88f8
Suggested fix
Cap dataLen the same way readString / readBytes already do, or just reuse readBytes:
data, err := readBytes(r, uint(dataLen))
This would apply the existing readBytesMaxUpfront guard.
Impact
Any Go service that calls tag.ReadFrom() on untrusted audio files (media uploads, metadata extraction) can be forced into a multi-GB allocation by a small crafted FLAC file.
Bug
readPictureBlockinvorbis.goreads a 4-bytedataLenfrom the input and passes it directly tomake([]byte, dataLen)without any size cap:A crafted FLAC file with
dataLen = 0x7FFFFFFFcauses a ~2 GB allocation from a 49-byte input. The allocation happens beforeio.ReadFullreturns EOF, so the memory is committed regardless.The rest of the codebase already has
readBytesMaxUpfront(10 MB cap) inreadBytes()/readString(), but this code path uses a rawmakeinstead.Reproduction
49-byte FLAC file (base64):
Decode and run:
Measured:
TotalAlloc delta = 2147520480 bytes (2147.5 MB)from a 49-byte file. Tested on current HEAD (3d75831).SHA-256 of poc.bin:
3ba94bb0597fa4689cad34e8f1e9866901cad38a64e80ab196504696322b88f8Suggested fix
Cap
dataLenthe same wayreadString/readBytesalready do, or just reusereadBytes:This would apply the existing
readBytesMaxUpfrontguard.Impact
Any Go service that calls
tag.ReadFrom()on untrusted audio files (media uploads, metadata extraction) can be forced into a multi-GB allocation by a small crafted FLAC file.