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) {