From c127fb41d972884ddffbb7407adc79ad026b2c4f Mon Sep 17 00:00:00 2001 From: Luigi Colluto Date: Sat, 11 Jul 2026 19:08:46 +0200 Subject: [PATCH] Bound GGUF metadata/tensor counts by file size before allocating parse_metadata() and parse_tensors() calloc() a table sized directly from the header-declared m->n_kv / m->n_tensors, with no check against the mapped file. A 24-byte file declaring n_kv = 2^32 makes parse_metadata() request ~137 GB up front -- a load-time DoS from a tiny crafted model. Each metadata/tensor entry occupies at least one byte in the file, so a count larger than the bytes remaining (c->size - c->pos) cannot be real; reject it before the allocation. --- ds4.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ds4.c b/ds4.c index 640511eb0..49c2c1a53 100644 --- a/ds4.c +++ b/ds4.c @@ -1857,6 +1857,10 @@ static void model_prefetch_cpu_mapping(const ds4_model *m) { /* Read the GGUF metadata table. Values stay in the mmap; we store offsets so * later validation can decode only the keys it needs. */ static void parse_metadata(ds4_model *m, ds4_cursor *c) { + /* n_kv comes from the header. Every entry consumes at least one byte in the + * file, so a count larger than the bytes remaining cannot be real; reject it + * before calloc so a tiny file can't request an enormous allocation. */ + if (m->n_kv > c->size - c->pos) ds4_die("GGUF metadata count exceeds file size"); m->kv = calloc((size_t)m->n_kv, sizeof(m->kv[0])); if (!m->kv) ds4_die("out of memory while allocating metadata table"); @@ -1887,6 +1891,10 @@ static void parse_metadata(ds4_model *m, ds4_cursor *c) { /* Read the tensor directory and convert relative GGUF offsets to absolute * mmap offsets. Tensor bytes are still never copied here. */ static void parse_tensors(ds4_model *m, ds4_cursor *c) { + /* As in parse_metadata: each tensor directory entry needs at least one byte + * in the file, so reject a count larger than the bytes remaining before the + * allocation. */ + if (m->n_tensors > c->size - c->pos) ds4_die("GGUF tensor count exceeds file size"); m->tensors = calloc((size_t)m->n_tensors, sizeof(m->tensors[0])); if (!m->tensors) ds4_die("out of memory while allocating tensor table");