Misc. bug: uncaught integer overflows during model loading

这个报错通常出现在加载形状异常的 GGUF 模型时,llama.cpp 在 tensor 解析阶段对元素总数或字节数的整数乘法溢出,触发 UBSan 报告。优先排查模型文件本身是否损坏或非标准 GGUF,并关注 gguf.cpp 中的元素数量校验逻辑。

快速结论:这个报错通常出现在加载形状异常的 GGUF 模型时,llama.cpp 在 tensor 解析阶段对元素总数或字节数的整数乘法溢出,触发 UBSan 报告。优先排查模型文件本身是否损坏或非标准 GGUF,并关注 gguf.cpp 中的元素数量校验逻辑。

适用环境:Issue 中确认的环境为 Linux x86_64,使用 Clang 14.0.6 构建,llama.cpp 版本 0.5.0-dev(build 709,commit 70596c4);受影响模块为 llama-server 和 llama-cli。Issue 未提供 CUDA、显卡、Python 或 PyTorch 版本信息,无需补充。

最快修复方案:暂无确认的一步修复方案。Issue 中讨论的修复思路是在 gguf.cpp 中改为逐维检查乘积,并在将类型读入 enum 之前先按整数读取并做范围检查,但尚未合并到正式发布版本。

注意事项:上述修复代码来自 Issue 评论者提出的最小修复示例,仅在其自有 loader 中验证(BEKO2210/statim PR #47),并非 llama.cpp 官方已合并的补丁。如果直接修改源码,需自行重新编译并确认不影响合法 GGUF 文件的加载。对于损坏模型的根因,仍未完全确认。

问题场景

用户使用 llama-cli 加载 GGUF 模型(命令为 llama-cli -m bug_model.gguf),在模型加载阶段触发未捕获的整数溢出。该问题是在对 llama.cpp 进行模糊测试(fuzzing)时发现的,涉及 tensor 解析过程;llama-server 同样受影响。

报错原文

Misc. bug: uncaught integer overflows during model loading

"/llama.cpp/ggml/src/ggml.c:1319:42: runtime error: unsigned integer overflow: 6917530127152709631 * 103903848824832 cannot be represented in type 'unsigned long'",
"    #0 0x12ab637 in ggml_nbytes /llama.cpp/ggml/src/ggml.c:1319:42",
"    #1 0x14afbe3 in gguf_init_from_reader(gguf_reader const&, gguf_init_params) /llama.cpp/ggml/src/gguf.cpp:786:34",
"    #2 0x14b36c3 in gguf_init_from_file_ptr /llama.cpp/ggml/src/gguf.cpp:956:12",
"    #3 0x14b36c3 in gguf_init_from_file /llama.cpp/ggml/src/gguf.cpp:1000:36",
"    #4 0x900dbb in llama_model_loader::llama_model_loader(gguf_context*, void (*)(ggml_tensor*, void*), void*, std::__cxx11::basic_string..., ...) /llama.cpp/src/llama-model-loader.cpp:565:28",
"    #5 0x52bfcf in llama_model_load(...) /llama.cpp/src/llama.cpp:318:28",
"    #6 0x529065 in llama_model_load_from_file_impl(...) /llama.cpp/src/llama.cpp:425:34",
"    #7 0x529832 in llama_model_load_from_file /llama.cpp/src/llama.cpp:466:12",
"    #8 0x4f11b1 in LLVMFuzzerTestOneInput /llama.cpp/fuzzers/fuzz_inference.cpp:63:19",
...

原因分析

根据 Issue 报告和评论确认,问题出在 GGUF 加载路径的整数溢出校验逻辑上,具体包含两个点:

第一,gguf_init_from_reader() 中的元素数量校验本身会先执行乘法再检查结果。校验代码试图用自带的算术提前判断 ggml_nelements() 是否溢出,但溢出恰恰发生在 ggml_nelements() 内部的乘法里;此外,如果某个维度为 0,或者乘法结果溢出成 0,ggml_nelements() > 0 条件为假,整个校验会被跳过,导致异常形状(如 [32, 5116089176692883472] 或 [2^62, 2, 0])漏过检查。

第二,tensor 类型在范围检查之前就被读入 enum。评论指出 gr.read(info.t.type) 会直接把磁盘上的 4 字节写入 enum ggml_type,若值超出 enum 范围,在 C++ 中属于未定义行为(UBSan 报告 load of value ... which is not a valid value for type 'ggml_type'),而随后的 info.t.type < 0 || >= GGML_TYPE_COUNT 检查已经太晚。

环境排查

  • 确认 llama.cpp 版本与构建:Issue 中为 0.5.0-dev(build 709,commit 70596c4),Clang 14.0.6,Linux x86_64。
  • 确认加载的 GGUF 模型是否来自可信来源,或是否由异常工具生成、是否可能损坏。
  • 确认是否开启了 UBSan 等运行时检测:该报错在普通构建下可能表现为静默溢出,而非直接崩溃。
  • 确认是否同时使用 llama-server 和 llama-cli 复现,以判断是否为同一加载路径问题。
  • Issue 未涉及其它依赖版本,不需要额外核对 Python、CUDA、PyTorch 或显卡驱动。

解决步骤

  1. 先确认问题是否由模型文件本身触发:用 Issue 中相同的 llama-cli -m bug_model.gguf 命令复现,并记录是否只有该模型出现。如果换用官方推荐的已知正常 GGUF 模型无法复现,基本可判断为异常 GGUF 形状导致。
  2. 在源码中定位 ggml/src/gguf.cpp 中 gguf_init_from_reader() 的元素数量校验段。可优先尝试把校验改为逐维检查的运行乘积写法,在每次乘法之前判断 n_elements > INT64_MAX / info.t.ne[j],避免零维度或溢出为 0 时跳过校验。
  3. 在同一函数中,把 tensor 类型读取改为先读入 int32_t,完成 [0, GGML_TYPE_COUNT) 范围检查后再转换为 ggml_type,避免非法值直接进入 enum。
  4. 如果不想修改 llama.cpp 源码,可在自有加载流程中,在调用 gguf_init_from_file() 之前先对模型文件的 tensor 形状做一轮校验,提前拒绝元素数量不可表示或维度为 0 的模型(Issue 评论者提到其项目 statim PR #47 采用了这种做法)。
  5. 若只是需要在本地绕过崩溃,回退到较旧且未遇到该问题的构建可作为临时手段,但这不构成根因修复,需明确记录。

验证方法

用修复后的构建重新运行 llama-cli -m bug_model.gguf。如果模型形状确实异常,应看到明确的错误日志(例如“total number of elements in tensor … is not representable”或“invalid ggml type”),而不是 UBSan 整数溢出报告;如果模型合法,应正常加载推理且日志与修复前一致。同时建议在正常 GGUF 模型上回归测试,确认逐维校验不会误拒合法文件。

参考来源

ggml-org/llama.cpp #29383

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 26579

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注