Commit 2149c00f4 for llama.cpp

commit 2149c00f4442dc59302e134a02e4c99d5f7ed9fc
Author: Daniel Kuts <kutz@ispras.ru>
Date:   Wed Sep 30 17:59:00 2026 +0300

    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

diff --git a/ggml/src/ggml.c b/ggml/src/ggml.c
index 7c931afb9..9bcabdbd3 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 8e8c2f0e6..75ceade7d 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) {