From 7675c555a13c9f473249e59a54db35032ce8e0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=A4=C3=9Fler?= Date: Sun, 1 Jun 2025 18:08:05 +0200 Subject: [PATCH] gguf: fix failure on version == 0 (#13956) --- ggml/src/gguf.cpp | 15 +++++++++------ tests/test-gguf.cpp | 8 +++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ggml/src/gguf.cpp b/ggml/src/gguf.cpp index dab228e1e..a0a318a29 100644 --- a/ggml/src/gguf.cpp +++ b/ggml/src/gguf.cpp @@ -347,6 +347,11 @@ struct gguf_context * gguf_init_from_file_impl(FILE * file, struct gguf_init_par int64_t n_tensors = 0; if (ok && gr.read(ctx->version)) { + if (ok && ctx->version == 0) { + GGML_LOG_ERROR("%s: bad GGUF version: %" PRIu32 "\n", __func__, ctx->version); + ok = false; + } + /* * bit layout is different when reading non-native endian models. * assuming that the GGUF version is 3, the non-native endian model @@ -354,18 +359,16 @@ struct gguf_context * gguf_init_from_file_impl(FILE * file, struct gguf_init_par * the last 4 hexadecimal digits to check if the model is the same * endianness as the host system. */ - if ((ctx->version & 0x0000FFFF) == 0x00000000) { + if (ok && (ctx->version & 0x0000FFFF) == 0x00000000) { GGML_LOG_ERROR("%s: failed to load model: this GGUF file version %" PRIu32 " is extremely large, is there a mismatch between the host and model endianness?\n", __func__, ctx->version); - gguf_free(ctx); - return nullptr; + ok = false; } - GGML_ASSERT(ctx->version > 0 && ctx->version <= 65535); - if (ctx->version == 1) { + if (ok && ctx->version == 1) { GGML_LOG_ERROR("%s: GGUFv1 is no longer supported, please use a more up-to-date version\n", __func__); ok = false; } - if (ctx->version > GGUF_VERSION) { + if (ok && ctx->version > GGUF_VERSION) { GGML_LOG_ERROR("%s: this GGUF file is version %" PRIu32 " but this software only supports up to version %d\n", __func__, ctx->version, GGUF_VERSION); ok = false; diff --git a/tests/test-gguf.cpp b/tests/test-gguf.cpp index eaf572c66..3f0c312e2 100644 --- a/tests/test-gguf.cpp +++ b/tests/test-gguf.cpp @@ -16,6 +16,7 @@ constexpr int offset_has_data = 3000; enum handcrafted_file_type { HANDCRAFTED_HEADER_BAD_MAGIC = 10, + HANDCRAFTED_HEADER_BAD_VERSION_0 = 15, HANDCRAFTED_HEADER_BAD_VERSION_1 = 20, HANDCRAFTED_HEADER_BAD_VERSION_FUTURE = 30, HANDCRAFTED_HEADER_BAD_N_TENSORS = 40, @@ -51,6 +52,7 @@ enum handcrafted_file_type { static std::string handcrafted_file_type_name(const enum handcrafted_file_type hft) { switch (hft) { case HANDCRAFTED_HEADER_BAD_MAGIC: return "HEADER_BAD_MAGIC"; + case HANDCRAFTED_HEADER_BAD_VERSION_0: return "HEADER_BAD_VERSION_0"; case HANDCRAFTED_HEADER_BAD_VERSION_1: return "HEADER_BAD_VERSION_1"; case HANDCRAFTED_HEADER_BAD_VERSION_FUTURE: return "HEADER_BAD_VERSION_FUTURE"; case HANDCRAFTED_HEADER_BAD_N_KV: return "HEADER_BAD_N_KV"; @@ -171,7 +173,10 @@ static FILE * get_handcrafted_file(const unsigned int seed, const enum handcraft helper_write(file, GGUF_MAGIC, 4); } - if (hft == HANDCRAFTED_HEADER_BAD_VERSION_1) { + if (hft == HANDCRAFTED_HEADER_BAD_VERSION_0) { + const uint32_t version = 0; + helper_write(file, version); + } else if (hft == HANDCRAFTED_HEADER_BAD_VERSION_1) { const uint32_t version = 1; helper_write(file, version); } else if (hft == HANDCRAFTED_HEADER_BAD_VERSION_FUTURE) { @@ -660,6 +665,7 @@ static std::pair test_handcrafted_file(const unsigned int seed) { const std::vector hfts = { HANDCRAFTED_HEADER_BAD_MAGIC, + HANDCRAFTED_HEADER_BAD_VERSION_0, HANDCRAFTED_HEADER_BAD_VERSION_1, HANDCRAFTED_HEADER_BAD_VERSION_FUTURE, HANDCRAFTED_HEADER_BAD_N_KV,