From 2149c00f4442dc59302e134a02e4c99d5f7ed9fc Mon Sep 17 00:00:00 2001 From: Daniel Kuts Date: Wed, 30 Sep 2026 17:59:00 +0300 Subject: [PATCH] ggml/gguf : fix integer overflow (#29384) * ggml: fix integer overflow guard for zero-element tensors * ggml: validate number of elements in tensor to prevent integer overflow * ggml: fix error print --- ggml/src/ggml.c | 9 +++++++++ ggml/src/gguf.cpp | 29 ++++++++++++++++++----------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c index 7c931afb99..9bcabdbd34 100644 --- a/ggml/src/ggml.c +++ b/ggml/src/ggml.c @@ -1780,6 +1780,15 @@ static struct ggml_tensor * ggml_new_tensor_impl( view_src = view_src->view_src; } + // validate number of elements to fit in int64_t + int64_t current_nelements = ne[0]; + for (int i = 1; i < n_dims; i++) { + if (ne[i] > 1) { + GGML_ASSERT(INT64_MAX / ne[i] > current_nelements); + current_nelements *= ne[i]; + } + } + size_t data_size = ggml_row_size(type, ne[0]); for (int i = 1; i < n_dims; i++) { data_size *= ne[i]; diff --git a/ggml/src/gguf.cpp b/ggml/src/gguf.cpp index 8e8c2f0e68..75ceade7d5 100644 --- a/ggml/src/gguf.cpp +++ b/ggml/src/gguf.cpp @@ -698,17 +698,24 @@ static struct gguf_context * gguf_init_from_reader(const struct gguf_reader & gr } // check that the total number of elements is representable - // (a zero-element tensor is trivially representable; the guard also avoids a division by zero below) - if (ok && ggml_nelements(&info.t) > 0 && - ((INT64_MAX/info.t.ne[1] <= info.t.ne[0]) || - (INT64_MAX/info.t.ne[2] <= info.t.ne[0]*info.t.ne[1]) || - (INT64_MAX/info.t.ne[3] <= info.t.ne[0]*info.t.ne[1]*info.t.ne[2]))) { - - GGML_LOG_ERROR("%s: total number of elements in tensor '%s' with shape " - "(%" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi64 ") is >= %" PRIi64 "\n", - __func__, info.t.name, info.t.ne[0], info.t.ne[1], info.t.ne[2], info.t.ne[3], INT64_MAX); - ok = false; - break; + // (a zero-element tensor is trivially representable) + if (ok) { + int64_t current_nelements = info.t.ne[0]; + for (int i = 1; i < GGML_MAX_DIMS; ++i) { + if (info.t.ne[i] > 1) { // 1 or 0 won't cause an overflow + if (INT64_MAX / info.t.ne[i] < current_nelements) { + ok = false; + break; + } + } + current_nelements *= info.t.ne[i]; + } + if (!ok) { + GGML_LOG_ERROR("%s: incorrect shape for a tensor '%s' may cause overflow errors: " + "(%" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi64 ") is >= INT64_MAX (%" PRIi64 ")\n", + __func__, info.t.name, info.t.ne[0], info.t.ne[1], info.t.ne[2], info.t.ne[3], INT64_MAX); + break; + } } } if (!ok) {