gguf-py: validate n_dims and guard against uint64 overflow in reader (#25401)

The Python GGUF reader lacked two guards the C++ loader has:
- n_dims read as uint32 with no GGML_MAX_DIMS bound -> crafted file with
  huge n_dims triggers oversized memmap read / OOM.
- np.prod(dims) on uint64 wraps silently -> a crafted dims triple can
  overflow to a tiny element count, passing an undersized read through.

Add a GGML_MAX_DIMS check and compute the element count with Python ints.

Fixes #25378
This commit is contained in:
hcl
2026-08-04 12:12:48 +03:00
committed by GitHub
parent 2e17f69ef4
commit 5788b510a1
3 changed files with 45 additions and 1 deletions
+1
View File
@@ -11,6 +11,7 @@ GGUF_MAGIC = 0x46554747 # "GGUF"
GGUF_VERSION = 3
GGUF_DEFAULT_ALIGNMENT = 32
GGML_QUANT_VERSION = 2 # GGML_QNT_VERSION from ggml.h
GGML_MAX_DIMS = 4 # GGML_MAX_DIMS from ggml.h
#
# metadata keys
+7 -1
View File
@@ -22,6 +22,7 @@ if __name__ == "__main__":
sys.path.insert(0, str(Path(__file__).parent.parent))
from gguf.constants import (
GGML_MAX_DIMS,
GGML_QUANT_SIZES,
GGUF_DEFAULT_ALIGNMENT,
GGUF_MAGIC,
@@ -266,6 +267,8 @@ class GGUFReader:
# Get Tensor Dimensions Count
n_dims = self._get(offs, np.uint32)
offs += int(n_dims.nbytes)
if n_dims[0] > GGML_MAX_DIMS:
raise ValueError(f'Tensor dimensions count {n_dims[0]} exceeds GGML_MAX_DIMS ({GGML_MAX_DIMS})')
# Get Tensor Dimension Array
dims = self._get(offs, np.uint64, n_dims[0])
@@ -326,7 +329,10 @@ class GGUFReader:
raise ValueError(f'Found duplicated tensor with name {tensor_name}')
tensor_names.add(tensor_name)
ggml_type = GGMLQuantizationType(raw_dtype[0])
n_elems = int(np.prod(dims))
# use Python ints: np.prod on uint64 wraps silently on overflow
n_elems = 1
for dim in dims.tolist():
n_elems *= int(dim)
np_dims = tuple(reversed(dims.tolist()))
block_size, type_size = GGML_QUANT_SIZES[ggml_type]
n_bytes = n_elems * type_size // block_size