You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

ggus (InfiniTensor/gguf) Shape-2 eager collection-alloc DoS -- PoC & measurements

Target: FORMAT=GGUF, IMPL=ggus (InfiniTensor gguf-rs crate) Pin: v0.5.1 / commit 2d879ca06302e570c524835a592c35631e9a2328 https://github.com/InfiniTensor/gguf.git

Sink

  • ggus/src/header.rs:22-27 -- GGufReader::read_header() casts the first 24 bytes of the input straight to a #[repr(C)] GGufFileHeader { magic:[u8;4], version:u32, tensor_count:u64, metadata_kv_count:u64 } via an unsafe raw pointer read. No range/sanity check on tensor_count or metadata_kv_count -- both are attacker-controlled u64s taken verbatim from a 24-byte file.
  • ggus/src/file.rs:76 -- IndexMap::with_capacity(header.metadata_kv_count as _)
  • ggus/src/file.rs:84 -- IndexMap::with_capacity(header.tensor_count as _) Both calls happen BEFORE any tensor/kv entry is actually read from the file, i.e. before any real bounds check against the file's actual size.

Why this "commits" (defeats G1: demand-paged mmap never actually commits)

IndexMap::with_capacity(n) (indexmap crate, hashbrown-backed) allocates in two steps:

  1. RawTable::with_capacity(n) -- ONE mmap for a combined ctrl-byte + data-slot buffer (~9 bytes/bucket observed for this K/V shape), and critically hashbrown's constructor EAGERLY memsets the control-byte region to 0xFF right there (a hard SIMD-group-probe invariant -- it cannot be made lazy). That memset is a genuine WRITE, i.e. real physical RSS commit, proportional to the (attacker-chosen) bucket count.
  2. Vec::with_capacity(n) for the ordered entries array -- lazy/uninitialized, does not itself commit memory, but the size of this request is also attacker-controlled and can independently blow available memory.

So a 24-byte file can force the process to either (a) commit real, measured gigabytes of RSS via the control-byte memset before anything else runs, or (b) request an allocation so large the global allocator's handle_alloc_error fires and the process aborts almost instantly, or (c) overflow hashbrown's own capacity arithmetic and panic before any allocation syscall is even attempted. All three are demonstrated below, each triggered from the SAME 24-byte file shape with only the tensor_count field varied.

PoC files (all exactly 24 bytes: "GGUF" + u32 version=3 + u64 tensor_count + u64 metadata_kv_count=0)

file tensor_count outcome (measured)
gguf_neg_control.gguf 3 Ok control: Err(Eos) after trivial alloc, RSS flat ~1.9-2.0 MB, exit 0
gguf_commit_1gib.gguf 939,524,096 (0x38000000) REAL RSS COMMIT to 1,050,624 KB (1.05 GiB), 262,228 minor page faults (1.024 GiB, matches RSS), then SIGABRT (signal 6) when the 2nd (entries Vec) alloc request (37.58 GB) is refused
gguf_abort_huge.gguf 137,438,953,472 (0x2000000000, the literal value from the task spec) Instant handle_alloc_error: "memory allocation of 2473901162512 bytes failed" (~2.47 TB combined ctrl+data layout) -> SIGABRT, <10ms, flat RSS
gguf_abort_max.gguf 18,446,744,073,709,551,615 (u64::MAX) Instant panic: "Hash table capacity overflow" at hashbrown-0.17.1/src/raw.rs:36 -> process exit 101, <10ms, flat RSS

How each was driven

Two PoC harnesses, same sink, two calling conventions:

  • poc_a_param / poc_b_abort / poc_a_commit / poc_neg_control -- build the 24-byte header in-memory and call ggus::GGuf::new(&data) directly.
  • poc_load_file <path.gguf> -- realistic threat model: std::fs::read(path) then ggus::GGuf::new(&data), i.e. exactly what a downstream model-loading application does with an untrusted file. This is the one that matters for the writeup -- it proves the literal 24-byte files in this directory are independently sufficient, with no in-memory-only construction required.

All four .gguf files above were re-run through poc_load_file (see gguf_*.file.time.log for the corresponding /usr/bin/time -v output) with identical results to the parameterized harness.

Key evidence (gguf_commit_1gib.gguf via poc_load_file, ulimit -v 16 GB)

[poc_load_file] loaded 24 bytes from gguf_commit_1gib.gguf
memory allocation of 37580963840 bytes failed
Command terminated by signal 6
        Maximum resident set size (kbytes): 1050624
        Minor (reclaiming a frame) page faults: 262228
        Exit status: 0   (this is time(1)'s own exit; the timed command itself died to SIGABRT)

262,228 minor faults * 4096 bytes/page = 1,074,342,912 bytes = 1.0247 GiB, matching the reported 1,050,624 KB (1.0018 GiB) Maximum RSS to within rounding -- i.e. essentially every resident page was freshly faulted in during this run, which is the direct, unambiguous signature of a real eager write (the hashbrown control-byte memset), not a virtual/lazy mmap reservation that was merely charged against the process's address-space accounting.

Negative control (gguf_neg_control.gguf, tensor_count=3): Maximum RSS 1,980 KB, 83 minor faults, exit 0, clean Err(Reading(Eos)) -- confirms the RSS growth above is capacity-driven, not an artifact of calling GGuf::new on a short file.

Reproduction

cd /home/wey/fuzz/ggus
cargo build --release        # pulls ggus @ pinned commit via git dependency
cd poc
./../target/release/poc_load_file gguf_neg_control.gguf     # baseline, exit 0
./../target/release/poc_load_file gguf_abort_huge.gguf      # instant abort, exit 134 (SIGABRT)
./../target/release/poc_load_file gguf_abort_max.gguf       # instant panic, exit 101
( ulimit -v 16000000; /usr/bin/time -v ./../target/release/poc_load_file gguf_commit_1gib.gguf )
  # ~45-60s wall time (WSL2/Hyper-V memory-accounting overhead at this scale);
  # watch `free -h` in another shell to see ~1GB RSS climb and release

Dedup note

Only public writeup for this bug SHAPE is GGML's C gguf_init_from_file (same missing-range-check pattern in a different language/implementation). No RustSec advisory, GHSA, or CVE names the ggus / InfiniTensor gguf crate as of 2026-07-17. This is a distinct, novel-for-this-implementation finding (G3: same-shape-different-impl converts).

Downloads last month
-
GGUF
Hardware compatibility
Log In to add your hardware

We're not able to determine the quantization variants.

Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support