Downloads · 30 days
24
47% of all-time downloads
MBM7/ggml-oom-abort-poc
ggml-oom-abort-poc is a machine learning model from MBM7. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
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 (ggmlinit), reached via ggml/src/gguf.cpp (ggufinitf…
Downloads · 30 days
24
47% of all-time downloads
All-time downloads
51
Public
Repo size
—
Likes
1
Public
Click a slice to open those files.
.md6.5 KB · 47%
From the Hugging Face model README
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.
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.
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
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.
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.
This exact function area (gguf_init_from_file_impl / mem_size computation / ggml_init) is under active, recent security research by multiple people:
gguf.cpp line 623 (different mechanism: a zero-dimension tensor bypasses an off-by-one < 0 vs. <= 0 check).n_dims/GGML_MAX_DIMS bound check in the Python gguf-py bindings (distinct from this C++ finding and from this reporter's other gguf-py findings).mem_size Calculation — Bypass of CVE-2025-53630 Fix"), in the same code region but a mechanistically distinct bug: that advisory involves an integer overflow that causes mem_size to wrap to a small value, so malloc succeeds 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.
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.
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.