Proof-of-concept material for a huntr Model Format Vulnerability report
against Mozilla-Ocho/llamafile (llamafile/zip.c + llamafile/llamafile.c).
The bug, verified against the live source fetched directly today
get_zip_cfile_compressed_size() (zip.c:33-47) returns int64_t -1 as an
error sentinel when a ZIP64 extra field is malformed/truncated (the loop
that scans extra-field records never finds a kZipExtraZip64 record with
enough content bytes for a 64-bit size).
llamafile.c:178 assigns this return value directly:
file->size is declared size_t (llamafile.c:61) - assigning -1 to a
size_t silently wraps to SIZE_MAX, with no check for the error sentinel
anywhere in this call site.
so this poisoned SIZE_MAX propagates out to any caller.
llamafile_read()'s in-memory branch (llamafile.c:377-386, used when
file->fp is NULL, which is the case throughout llamafile_open_zip):
c
1size_t remain = file->size - file->position;// now enormous, not real2size_t amt =Min(len, remain);// effectively just len3memcpy(ptr, file->content + file->position, amt);// reads past real mmap
remain is no longer bounded by the real (small) mapped region, so amt
is effectively whatever the caller requests - memcpy can read past the
real mmap'd buffer.
Reachability (per the original researcher's patch-file tracing, not
independently re-verified in this repo)
The poisoned llamafile_size(lfile) value is passed as nbytes_remain into
llamafile's vendored gguf_reader constructor
(llama.cpp.patches/patches/ggml_src_gguf.cpp.patch) - the exact variable
upstream gguf.cpp uses to bounds-check every subsequent GGUF read (numbers,
strings, arrays). Poisoning it to SIZE_MAX disables that protection for
the rest of parsing, not just one read. This is the real, active code path
used whenever llamafile loads a .gguf/.llamafile model (confirmed via
#ifdef COSMOCC patch application, not dead/unused code despite misleading
"UNUSED externally" comments in llamafile.h).
Honest limits (not swept under the rug)
No PoC ZIP file/binary was built or run - llamafile is built with the
Cosmopolitan Libc toolchain (a non-standard, portable-executable-producing
C toolchain), which was not available to set up on this host within a
reasonable scope for this report. This finding is source-level: the
poisoning mechanism (zip.c -> llamafile.c -> llamafile_size() ->
llamafile_read()) was verified by direct reading of the current live
source (fetched today), not by triggering an actual crash/OOB-read against
a compiled llamafile binary.
Impact: Denial of Service / out-of-bounds read - an attacker who can supply
or influence a .llamafile/zip-embedded .gguf with a malformed ZIP64
extra field can poison the size llamafile believes the embedded file has to
SIZE_MAX, disabling the bounds-check llama.cpp's GGUF parser relies on for
the remainder of parsing.
Suggested fix: Check get_zip_cfile_compressed_size()'s return value for
-1 at the llamafile.c:178 call site (and any other caller) before
assigning it to a size_t field, and fail the zip-open operation instead of
silently wrapping to SIZE_MAX.