YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
llama.cpp / GGML β Unrecoverable Process Abort via Oversized Tensor Allocation (Reachable Assertion DoS)
Status: Preparing for Huntr submission
Target: ggml-org/llama.cpp β native GGML/GGUF C/C++ loader (not the Python gguf-py bindings)
File / function: ggml/src/ggml.c (ggml_init), reached via ggml/src/gguf.cpp (gguf_init_from_reader β gguf_init_from_file)
Class: CWE-617 (Reachable Assertion)
Severity: Medium β a clean crash (no memory corruption), but on the real production model-loading path, unconditional, and uncatchable by any embedding application.
Summary
ggml_init() allocates its working memory buffer via ggml_aligned_malloc(mem_size), where mem_size is derived from a tensor's declared shape in a GGUF file. If the requested size is large enough that the allocation fails β which does not require any integer overflow, just an honestly large size that exceeds available system memory β the very next line fires an assertion:
struct ggml_context * ggml_init(struct ggml_init_params params) {
...
*ctx = (struct ggml_context) {
...
/*.mem_buffer = */ params.mem_buffer ? params.mem_buffer
: ggml_aligned_malloc(mem_size),
...
};
GGML_ASSERT(ctx->mem_buffer != NULL); // fires here on malloc failure
GGML_ASSERT calls ggml_abort(), which β confirmed by reading its source β calls the registered g_abort_callback if one exists, but unconditionally calls abort() immediately afterward regardless. There is no way for an embedding application to intercept or recover from this: no C++ exception is thrown, no error code is returned. The process terminates outright.
This is reached directly from the real model-loading call chain used by any application built on llama.cpp β server, CLI, or third-party integration β not example/demo code.
Proof of Concept
poc_ggml_oom_abort_dos.py hand-builds a minimal, 96-byte GGUF file (no dependency on any writer library): a single tensor declared with 500,000,000,000 float32 elements (~2 TB), zero KV metadata, zero real tensor data (the crash happens at allocation time, before any data would be read).
python3 poc_ggml_oom_abort_dos.py [path to a compiled llama-gguf binary]
Or manually, after building ggml-org/llama.cpp:
cmake -B build -DLLAMA_BUILD_EXAMPLES=ON
cmake --build build --target llama-gguf
./build/bin/llama-gguf minimal_alloc_crash.gguf r
Result
ggml_aligned_malloc: insufficient memory (attempted to allocate 1907348.63 MB)
ggml/src/ggml.c:1643: GGML_ASSERT(ctx->mem_buffer != NULL) failed
Aborted (exit code 134)
100% reproducible.
How this was found
Mutation fuzzing (500 trials, 1β6 random byte flips per trial on a legitimate ~13KB test GGUF file generated by llama.cpp's own examples/gguf/gguf.cpp writer) surfaced this crash, distinguishing real SIGSEGV/unusual SIGABRT outcomes from the many expected, gracefully-handled GGML_ASSERT-with-clear-error-message aborts that the parser correctly produces for most malformed input. The crash was then reduced to this clean, minimal, single-cause 96-byte reproduction.
The same fuzzing run also found an unrelated NULL pointer dereference (CWE-476) in examples/gguf/gguf.cpp:161, where the example/demo code calls gguf_get_version(ctx) without checking whether gguf_init_from_file() returned NULL. This second issue was confirmed to be demo-code-only: the real production loader (src/llama-model-loader.cpp:553-555) correctly checks if (metadata == nullptr) { throw std::runtime_error(...); }, so it does not affect any real inference pipeline. Not included as a primary finding here for that reason.
Relationship to other known issues in this area (included for transparency)
This exact function area (gguf_init_from_file_impl / mem_size computation / ggml_init) is under active, recent security research by multiple people:
- An unrelated, already-published PoC for a division-by-zero in
gguf.cppline 623 (different mechanism: a zero-dimension tensor bypasses an off-by-one< 0vs.<= 0check). - A very recently reported issue describing a missing
n_dims/GGML_MAX_DIMSbound check in the Pythongguf-pybindings (distinct from this C++ finding and from this reporter's othergguf-pyfindings). - Most relevantly, an active GitHub Security Advisory, GHSA-3p4r-fq3f-q74v ("Heap Buffer Overflow via Integer Overflow in
mem_sizeCalculation β Bypass of CVE-2025-53630 Fix"), in the same code region but a mechanistically distinct bug: that advisory involves an integer overflow that causesmem_sizeto wrap to a small value, somallocsucceeds with an undersized buffer, and a subsequent tensor-data write overflows it β genuine heap corruption, RCE-capable. This PoC's bug is the opposite failure mode: a large, non-overflowing size request that correctly fails to allocate, but whose failure path is an uncatchable process abort rather than a graceful, catchable error.
Given this, some triagers may treat a clean OOM-induced abort as lower priority than active memory-corruption issues, or possibly as intentional defensive behavior rather than a distinct vulnerability. It's included here regardless because an uncatchable crash on the production model-loading path of a widely embedded inference engine is a legitimate availability concern in its own right β e.g., a multi-tenant model-serving service that loads user-supplied GGUF files can be taken down entirely by a 96-byte file, with no way for the service to validate or reject the file gracefully first.
Suggested fix
Before calling ggml_aligned_malloc(mem_size) in ggml_init(), either validate mem_size against a configurable sane maximum and return an error through the normal gguf_init_from_file failure path (as is already done for other malformed-input cases), or have ggml_init() return NULL on allocation failure instead of asserting, letting callers handle it the same way they already handle other gguf_init_from_file failures.
Disclosure
ggml-org/llama.cpp's own private security disclosure program is currently disabled ("Emails will be ignored... submit patches as public PRs"), so this is being reported via Huntr (GGML is a listed $1500 bounty target). Please do not use this PoC against production systems you do not own or have explicit permission to test.
- Downloads last month
- 10
We're not able to determine the quantization variants.