Skip to content

gguf: fix division by zero in tensor dimension validation - #1517

Closed
Ashutosh0x wants to merge 1 commit into
ggml-org:masterfrom
Ashutosh0x:fix/gguf-division-by-zero-crash
Closed

gguf: fix division by zero in tensor dimension validation#1517
Ashutosh0x wants to merge 1 commit into
ggml-org:masterfrom
Ashutosh0x:fix/gguf-division-by-zero-crash

Conversation

@Ashutosh0x

@Ashutosh0x Ashutosh0x commented May 28, 2026

Copy link
Copy Markdown

$\textcolor{red}{\textbf{(USER WAS BANNED FOR THIS POST)}}$

Summary

A crafted GGUF file with a zero-valued tensor dimension (ne[1]=0) causes an unconditional division-by-zero crash (SIGFPE) in the GGUF parser. The crash occurs at the element count overflow check in gguf_init_from_reader(). A 73-byte file is sufficient.

Root Cause

The tensor dimension validation at line 686 rejects negative values:

if (info.t.ne[j] < 0) {  // ne == 0 passes this check!

But the overflow check at line 695 divides by ne[1], ne[2], and ne[3]:

if (ok && ((INT64_MAX/info.t.ne[1] <= info.t.ne[0]) ||    // div by zero if ne[1]==0
           (INT64_MAX/info.t.ne[2] <= ...) ||               // div by zero if ne[2]==0
           (INT64_MAX/info.t.ne[3] <= ...))) {              // div by zero if ne[3]==0

When ne[1] = 0, the expression INT64_MAX / 0 triggers undefined behavior — on all tested platforms this results in SIGFPE (arithmetic exception), killing the process immediately.

This is not a resource exhaustion issue — there is no allocation, no gradual failure, no bad_alloc to catch. The process crashes unconditionally before any memory is allocated.

PoC

import struct

buf  = b"GGUF"                      # magic
buf += struct.pack("<I", 3)          # version
buf += struct.pack("<q", 1)          # n_tensors
buf += struct.pack("<q", 0)          # n_kv
buf += struct.pack("<Q", 1) + b"x"  # tensor name "x"
buf += struct.pack("<I", 2)          # n_dims = 2
buf += struct.pack("<q", 1)          # ne[0] = 1
buf += struct.pack("<q", 0)          # ne[1] = 0  *** CRASH ***
buf += struct.pack("<i", 0)          # type = F32
buf += struct.pack("<Q", 0)          # offset = 0

open("crash.gguf", "wb").write(buf)  # 73 bytes
$ ./build/bin/gguf-info crash.gguf
Floating point exception (core dumped)

Impact

  • Crash type: SIGFPE (undefined behavior, not catchable via try/catch)
  • Affected: Any application using gguf_init_from_file() — llama.cpp, whisper.cpp, Ollama, LM Studio, etc.
  • Attack vector: User loads a malicious GGUF model file
  • File size: 73 bytes

Fix

One-line change: ne[j] < 0ne[j] <= 0

A tensor dimension of zero is invalid in the GGUF format — no legitimate model has zero-element dimensions. This ensures ne[1], ne[2], ne[3] are all ≥ 1 before the division.

CC: @JohannesGaessler

A crafted GGUF file with ne[1]=0, ne[2]=0, or ne[3]=0 causes a
division by zero (SIGFPE) at the overflow check:

    INT64_MAX/info.t.ne[1] <= info.t.ne[0]

The existing validation only rejects negative dimensions (ne < 0),
but ne == 0 passes through and reaches the division. This crashes
the process unconditionally - no resource exhaustion, no graceful
error handling, just an immediate SIGFPE.

A 73-byte crafted file is sufficient to trigger the crash.

Fix: change the validation from ne < 0 to ne <= 0. A tensor
dimension of zero is invalid in GGUF model files.
@JohannesGaessler

Copy link
Copy Markdown
Contributor

@ggerganov can you please give me the permissions needed to close PRs in the ggml repository?

@Green-Sky

Copy link
Copy Markdown
Contributor

Btw, we need to more rigorously check for gguf zero sized tensors and abort. Also mark it somewhere in the gguf spec, that zero sized tensors are malformed.

@JohannesGaessler

Copy link
Copy Markdown
Contributor

Well, the problem with zero-sized tensors is that you are in fact allowed to create them via the ggml API and they are being used in llama.cpp for some tensors that are disabled (to have a constant graph topology). So the GGUF code should in turn also be able to read zero-sized tensors in order to be consistent.

@ggerganov

Copy link
Copy Markdown
Member

@ggerganov can you please give me the permissions needed to close PRs in the ggml repository?

Should have access now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants