Misc. bug: stack buffer overflow in clip_encode MiniCPM-V position buckets via malicious mmproj (bucket_coords_h[1024] written for i < pos_h

该报错(stack buffer overflow in clip_encode MiniCPM-V position buckets via malicious mmproj (bucket_coords_h[1024] written for i < pos_h))出现在 llama.cpp/l

快速结论:该报错(stack buffer overflow in clip_encode MiniCPM-V position buckets via malicious mmproj (bucket_coords_h[1024] written for i < pos_h))出现在 llama.cpp/libllama 的 mtmd 视觉编码路径加载 MiniCPM-V 系 mmproj 并编码图片时,固定 1024 项的栈数组被超出实际 patch 数的 pos_h/pos_w 写入。优先确认 mmproj 来源是否可信,并升级到已合入修复的版本。

适用环境:Issue 中已验证:Windows x64;受影响构建为 b10252(LM Studio 2.28.2 后端 llama.cpp-win-x86_64-avx2-2.28.2,mtmd.dll),源码为当前 master ad1de39e;复现亦在 4a899373 上用 -fsanitize=undefined 构建验证。作者称该缺陷为平台无关 C++。Python、CUDA、PyTorch、显卡型号未见明确记录。

最快修复方案:Issue 评论明确:由 #29276 修复(2026-09-22 合并),resampler(MiniCPM-V)与 SigLIP 路径上固定的 int bucket_coords_h[1024]/bucket_coords_w[1024] 已替换为按实际 patch 数分配大小的 vector,并附代码注释说明越界。升级到包含该提交的 llama.cpp 版本即可。

注意事项:触发不限于被篡改的 mmproj:评论指出,使用官方未改动的 openbmb/MiniCPM-V-2_6-gguf mmproj,输入一张极端长宽比图片(如 15000×1 PPM)即可越界,因此修复须不依赖 patch_size/image_size 配置。评论另提示一处未修的加固点:positions(pos_h * pos_w) 仍以 int 计算乘积,极端 mmproj 下可能回绕并抛 std::length_error(仅中止/DoS,未找到可破坏内存的路径);建议改用 int64_t/size_t,此点尚未确认已修复。

问题场景

用户在 llama.cpp 的 mtmd 多模态路径中加载 MiniCPM-V 系 mmproj(PROJECTOR_TYPE_MINICPMV 或 PROJECTOR_TYPE_MINICPMV4_6),通过 mtmd_init_from_file 初始化、mtmd_tokenize → mtmd_encode_chunk 编码图片时触发。两种典型入口:一是加载来源不明的 mmproj(如 clip.vision.patch_size = 1、image_size = 2048),使很小的图片被 llava-UHD 预处理放大到 2048×2048;二是使用标准未改动 mmproj 但输入长宽比极端的图片(评论给出 15000×1 PPM 的复现),使 overview 宽度对应 pos_w = 1071 > 1024。

报错原文

Misc. bug: stack buffer overflow in clip_encode MiniCPM-V position buckets via malicious mmproj (bucket_coords_h[1024] written for i < pos_h)

clip.cpp:4658:21: runtime error: index 1024 out of bounds for type 'int[1024]'
clip.cpp:4662:67: runtime error: index 1024 out of bounds for type 'int[1024]'
clip.cpp:4658:42: runtime error: inf is outside the range of representable values of type 'int'
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==29342==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x003800000038
==29342==The signal is caused by a WRITE memory access.
UndefinedBehaviorSanitizer: nested bug in the same thread, aborting.

原因分析

tools/mtmd/clip.cpp 中 MiniCPM-V 分支用固定的 int bucket_coords_h[1024] 和 int bucket_coords_w[1024] 栈数组填充位置桶,循环上界为 pos_h = image_height / patch_size、pos_w = image_width / patch_size,但二者均未与 1024 做边界检查。image_size <= 8192 的检查无法兜底:patch_size = 1 时循环上界仍可达 8192。溢出长度可控、写入内容为 floor(70*i/pos_h),足以破坏相邻栈数据并导致 SEGV。触发面比最初报告更广:mtmd-image.cpp 的 llava-UHD 预处理(get_best_resize,allow_upscale=true)只约束总像素量而不单独限制单边尺寸,极端长宽比图片即可让 pos_w 超过 1024,无需恶意 mmproj。根因提交为 d565bb2f(#8967,2024-08-16)。

环境排查

  • 确认 llama.cpp / libllama / mtmd 的构建来源与提交号:受影响实例为 b10252(LM Studio 2.28.2 后端),源码基线 ad1de39e;复现基线 4a899373。
  • 确认是否已包含 #29276(2026-09-22 合并);未包含则仍受此问题影响。
  • 检查所使用的 mmproj 来源与元数据:clip.projector_type 是否为 resampler(MiniCPM-V 路径),clip.vision.patch_size 与 clip.vision.image_size 取值是否异常(如 patch_size = 1)。
  • 确认编码输入图片的尺寸与长宽比,尤其是单边远大于 448 的细长图片。
  • Issue 未提供 Python、CUDA、PyTorch、显卡等版本信息,这些不是判断依据。

解决步骤

  1. 升级或重新编译 llama.cpp,使用包含 #29276 的版本;该修复将 MiniCPM-V(resampler)和 SigLIP 路径上的固定 1024 项栈数组替换为按实际 patch 数大小的 vector。
  2. 升级前如需临时规避,仅加载可信来源的 mmproj,并避免向该路径提交极端长宽比图片;注意评论已证明这只能降低、不能消除暴露面。
  3. 重新验证后在当前 master 上确认不再出现该栈溢出;如需进一步加固,可将 positions(pos_h * pos_w) 的乘积改为 int64_t/size_t 计算(评论建议,Issue 未确认已修复)。
  4. 若使用的是 LM Studio 等第三方打包后端,需等待其更新到含修复的 llama.cpp 版本。

验证方法

用同一 mmproj 与同一张图(含评论中的 15000×1 PPM 边界样本)走 mtmd_init_from_file → mtmd_tokenize → mtmd_encode_chunk,确认不再出现 clip.cpp 的 index … out of bounds for type ‘int[1024]’ 报错与 UBSan SEGV;在 -fsanitize=undefined 构建下重新运行复现可作更严格确认。

参考来源

ggml-org/llama.cpp #27166

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 29359

发表回复

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