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
This commit is contained in:
Daniel Kuts
2026-09-30 17:59:00 +03:00
committed by GitHub
parent 876c75b1f6
commit 2149c00f44
2 changed files with 27 additions and 11 deletions
+9
View File
@@ -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];
+18 -11
View File
@@ -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) {