Repository navigation
gguf-py : add size guards to GGUFReader - #27188
Conversation
Guard kv_count, tensor_count, string length, and array length against crafted values that cause unbounded allocation or hangs. Assisted-by: opencode
They are not part of |
When no_alloc=true, gguf_init_from_reader accepted files where the tensor data section (computed from header claims) exceeded the remaining file size. This allowed crafted GGUF files to pass validation while having insufficient data, leading to OOB reads when the loader later mapped tensor data from the file. Assisted-by: opencode
Per review feedback, the limits are not part of gguf.h but are arbitrary limits defined in gguf.cpp, so define them locally in the reader instead of exporting them from constants. Assisted-by: opencode
|
Done. Moved the limits into gguf_reader.py as module-level constants. Removed from constants.py. |
CISC
left a comment
There was a problem hiding this comment.
You can revisit gguf.cpp changes in its own PR if you like.
|
@CISC This PR closes a DoS gap in the gguf-py reader: a crafted GGUF (43 bytes, array length 2^63) hangs the reader with unbounded memory growth (~120MB/s), and the PyPI gguf package (0.19.0, built from this directory) is still affected until a new release - an attacker who merely distributes a malicious GGUF can stall any client/loader that parses it. Given the earlier loader CVEs on this project (e.g. CVE-2026-27940), would you consider requesting a CVE/GHSA for this one as well ? |
See #26892 (comment) |
* gguf-py : add size guards to GGUFReader Guard kv_count, tensor_count, string length, and array length against crafted values that cause unbounded allocation or hangs. Assisted-by: opencode * gguf : validate tensor data section fits within file When no_alloc=true, gguf_init_from_reader accepted files where the tensor data section (computed from header claims) exceeded the remaining file size. This allowed crafted GGUF files to pass validation while having insufficient data, leading to OOB reads when the loader later mapped tensor data from the file. Assisted-by: opencode * gguf-py : move size limits into gguf_reader.py Per review feedback, the limits are not part of gguf.h but are arbitrary limits defined in gguf.cpp, so define them locally in the reader instead of exporting them from constants. Assisted-by: opencode * remove gguf.ccp changes --------- Co-authored-by: Sigbjørn Skjæret <sigbjorn.skjaeret@huggingface.co>
* gguf-py : add size guards to GGUFReader Guard kv_count, tensor_count, string length, and array length against crafted values that cause unbounded allocation or hangs. Assisted-by: opencode * gguf : validate tensor data section fits within file When no_alloc=true, gguf_init_from_reader accepted files where the tensor data section (computed from header claims) exceeded the remaining file size. This allowed crafted GGUF files to pass validation while having insufficient data, leading to OOB reads when the loader later mapped tensor data from the file. Assisted-by: opencode * gguf-py : move size limits into gguf_reader.py Per review feedback, the limits are not part of gguf.h but are arbitrary limits defined in gguf.cpp, so define them locally in the reader instead of exporting them from constants. Assisted-by: opencode * remove gguf.ccp changes --------- Co-authored-by: Sigbjørn Skjæret <sigbjorn.skjaeret@huggingface.co>
Overview
GGUFReader(gguf-py) currently trusts string and array length fields incrafted GGUF files, which can cause an infinite loop with unbounded memory
growth. Verified live: a 43-byte GGUF with an array length of 2^63 hangs
gguf==0.19.0on PyPI (no return within 20s, RAM grows ~120MB/s).This PR adds the same limits that the C++ parser already has
(
GGUF_MAX_STRING_LENGTH/GGUF_MAX_ARRAY_ELEMENTSfrom gguf.h) to thePython reader:
constants.py: addGGUF_MAX_STRING_LENGTHandGGUF_MAX_ARRAY_ELEMENTSgguf_reader.py: reject string length, array length, tensor count, andKV count above the limits with a fast
ValueError; also reject stringsthat exceed the remaining file size (parity with the C++ loader)
Additional information
Crafted variants verified: kv_count=2^63, tensor_count=2^63, string_len=2^63,
string exceeding file size, nested array length 2^62 - all raise
ValueErrorimmediately; a valid GGUF still loads.
tests/test_gguf_reader_validation.pyand existing gguf-py tests pass (7/7).
Note: the PyPI
ggufpackage (0.19.0, built from this directory) is stillaffected; a new release will be needed after merge.
Requirements