mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-10-01 05:56:52 +02:00
gguf : reject tensor size that wraps after padding (#26979)
GGML_PAD(nbytes, alignment) wraps to 0 when nbytes is within (alignment - 1) of SIZE_MAX, which silently bypassed the size overflow guard in gguf_init_from_reader. Reject the tensor before padding when nbytes + (alignment - 1) would overflow. Adds a test-gguf handcrafted case (F32, ne = [4, 2^30-1, 2^30+1, 1]) whose ggml_nbytes = 2^64 - 16 lands in the wrap window. Fails on master, passes with the guard.
This commit is contained in:
+10
-1
@@ -792,7 +792,16 @@ static struct gguf_context * gguf_init_from_reader(const struct gguf_reader & gr
|
||||
gguf_free(ctx);
|
||||
return nullptr;
|
||||
}
|
||||
size_t padded_size = GGML_PAD(ggml_nbytes(&ti.t), ctx->alignment);
|
||||
const size_t nbytes = ggml_nbytes(&ti.t);
|
||||
// GGML_PAD adds (alignment - 1) to nbytes. when nbytes is near
|
||||
// SIZE_MAX this wraps to 0 and makes the check below dead.
|
||||
if (nbytes > SIZE_MAX - (ctx->alignment - 1)) {
|
||||
GGML_LOG_ERROR("%s: tensor '%s' size %zu overflows after padding (alignment %zu)\n",
|
||||
__func__, ti.t.name, nbytes, ctx->alignment);
|
||||
gguf_free(ctx);
|
||||
return nullptr;
|
||||
}
|
||||
const size_t padded_size = GGML_PAD(nbytes, ctx->alignment);
|
||||
if (SIZE_MAX - ctx->size < padded_size) {
|
||||
GGML_LOG_ERROR("%s: tensor '%s' size overflow, cannot accumulate size %zu + %zu\n",
|
||||
__func__, ti.t.name, ctx->size, padded_size);
|
||||
|
||||
@@ -40,6 +40,7 @@ enum handcrafted_file_type {
|
||||
HANDCRAFTED_TENSORS_ZERO_DIM = 35 + offset_has_tensors,
|
||||
HANDCRAFTED_TENSORS_NE_TOO_BIG = 40 + offset_has_tensors,
|
||||
HANDCRAFTED_TENSORS_NBYTES_TOO_BIG = 45 + offset_has_tensors,
|
||||
HANDCRAFTED_TENSORS_NBYTES_PAD_WRAP = 46 + offset_has_tensors,
|
||||
HANDCRAFTED_TENSORS_BAD_TYPE = 50 + offset_has_tensors,
|
||||
HANDCRAFTED_TENSORS_BAD_OFFSET = 60 + offset_has_tensors,
|
||||
HANDCRAFTED_TENSORS_DUPLICATE_NAME = 70 + offset_has_tensors,
|
||||
@@ -80,6 +81,7 @@ static std::string handcrafted_file_type_name(const enum handcrafted_file_type h
|
||||
case HANDCRAFTED_TENSORS_ZERO_DIM: return "TENSORS_ZERO_DIM";
|
||||
case HANDCRAFTED_TENSORS_NE_TOO_BIG: return "TENSORS_NE_TOO_BIG";
|
||||
case HANDCRAFTED_TENSORS_NBYTES_TOO_BIG: return "TENSORS_NBYTES_TOO_BIG";
|
||||
case HANDCRAFTED_TENSORS_NBYTES_PAD_WRAP: return "TENSORS_NBYTES_PAD_WRAP";
|
||||
case HANDCRAFTED_TENSORS_BAD_TYPE: return "TENSORS_BAD_TYPE";
|
||||
case HANDCRAFTED_TENSORS_BAD_OFFSET: return "TENSORS_BAD_OFFSET";
|
||||
case HANDCRAFTED_TENSORS_DUPLICATE_NAME: return "TENSORS_DUPLICATE_NAME";
|
||||
@@ -250,6 +252,13 @@ static FILE * get_handcrafted_file(const unsigned int seed, const enum handcraft
|
||||
tensor_configs[1] = { GGML_TYPE_I8, { 0x7FFFFFFFFFFFFFC0, 1, 1, 1 } };
|
||||
}
|
||||
|
||||
if (hft == HANDCRAFTED_TENSORS_NBYTES_PAD_WRAP) {
|
||||
tensor_configs.resize(1);
|
||||
// F32 with ne = [4, 2^30-1, 2^30+1, 1] so ggml_nbytes = 2^64 - 16.
|
||||
// this hits the GGML_PAD wrap window: pad wraps to 0.
|
||||
tensor_configs[0] = { GGML_TYPE_F32, { 4, INT64_C(1073741823), INT64_C(1073741825), 1 } };
|
||||
}
|
||||
|
||||
if (hft == HANDCRAFTED_HEADER_BAD_N_TENSORS) {
|
||||
const uint64_t n_tensors = -1;
|
||||
helper_write(file, n_tensors);
|
||||
@@ -774,6 +783,7 @@ static std::pair<int, int> test_handcrafted_file(const unsigned int seed) {
|
||||
HANDCRAFTED_TENSORS_ZERO_DIM,
|
||||
HANDCRAFTED_TENSORS_NE_TOO_BIG,
|
||||
HANDCRAFTED_TENSORS_NBYTES_TOO_BIG,
|
||||
HANDCRAFTED_TENSORS_NBYTES_PAD_WRAP,
|
||||
HANDCRAFTED_TENSORS_BAD_TYPE,
|
||||
HANDCRAFTED_TENSORS_BAD_OFFSET,
|
||||
HANDCRAFTED_TENSORS_DUPLICATE_NAME,
|
||||
|
||||
Reference in New Issue
Block a user