[Bug]: Granite4 Vision mmproj with downsample_window_side=0 crashes at load (integer division by zero in warmup graph build)

Open Beginner friendly
#27,222 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
cpp
Domain
backend

Research direction

Start at tools/mtmd/models/granite4-vision.cpp and the GRANITE4_VISION branch of clip.cpp, where the downsample sides are read before graph warmup. Reproduce with gen_mmproj_granite4.py using window_side=0, then verify the loader rejects it without reaching the division sites; the window_side=8 control should still load and encode.

Written by the indexing model from the issue text.

Description

Git commit

The bug is reachable at current HEAD (ad1de39e, 2026-08-15) and was introduced by 64086f2b "model, mtmd: Granite4 Vision (#23545)".

Operating system

Windows (0xC0000094) and Linux (SIGFPE), x86_64. Prebuilt CPU backend. No GPU.

Steps to reproduce the bug
  1. Craft a minimal granite4-vision mmproj GGUF where clip.vision.proj.sample.window_side = 0 (u32, read with no validation — load_hparams GRANITE4_VISION branch, b10252 clip.cpp:1858-1859). Generator (52 F32 tensors, key dims: v.position_embd.weight ne = (n_embd, side²), v.proj_blk.0.img_pos (n_embd, window_side², n_windows), v.proj_blk.0.query (n_embd, query_side², 1)): python3 gen_mmproj_granite4.py g4w0.gguf 0 384. Control with window_side=8 loads and encodes fine.
  2. Load it with mtmd_init_from_file (default warmup=true).

Observed (Windows, LM Studio backend mtmd.dll):

[chk] params: use_gpu=0 warmup=1 n_threads=4
... load_tensors: loaded 53 tensors ...
[log INFO] get_dummy_batch: warmup with image size = 384 x 384
[VEH] exception 0xC0000094 at rip=... module=mtmd.dll rva=B2D56

gdb on Linux, b10252 Debug build:

Program received signal SIGFPE, Arithmetic exception.
#0 clip_graph_granite4_vision::build_block (..., image_side=24, window_side=0, query_side=4, ...)
   at tools/mtmd/models/granite4-vision.cpp:63        # const int n = image_side / window_side;
#1 ... #2 reserve_compute_meta ... #7 warmup ... #8 clip_init #9 mtmd_init_from_file

Same GGUF crashes HEAD ad1de39e at granite4-vision.cpp:87 (same line moved). Other division sites with the same divisor: clip.cpp:4043 (clip_n_output_tokens), clip.cpp:5135 (win_idx upload), HEAD granite4-vision.cpp:388 anyres path.

Expected behavior

load_hparams should reject zero downsample sides:

if (hparams.downsample_window_side == 0 || hparams.downsample_query_side == 0) {
    throw std::runtime_error("granite4_vision: downsample_window_side/query_side must be non-zero");
}
Other
  • Integer divide-by-zero — DoS, not memory corruption.
  • Crash happens at load time (warmup graph build), before any user image; in GUI apps built on mtmd (e.g. LM Studio), merely mounting such an mmproj crashes the process.
  • PoC generator gen_mmproj_granite4.py available; happy to attach.
Dominant language
C++
Stars
129k
Forks
23.5k
Avg merge
2d 11h
Merged PRs (30d)
411

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from ggml-org/llama.cpp

All issues in ggml-org/llama.cpp

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.