ollama qwen3next converter unbounded allocation PoC (source-verified)
Proof-of-concept material for a huntr Model Format Vulnerability report
against ollama/ollama,
convert/convert_qwen3next.go:226-233 (qwen3NextInferNextNPredictLayers).
The bug, verified against the live source fetched directly today
var n int64
if err := binary.Read(f, binary.LittleEndian, &n); err != nil {
f.Close()
return 0, err
}
b := bytes.NewBuffer(make([]byte, 0, n))
if _, err = io.CopyN(b, f, n); err != nil {
f.Close()
return 0, err
}
An 8-byte little-endian int64 length is read directly from an untrusted
model file and used, with no upper-bound check, to pre-allocate a buffer
via make([]byte, 0, n). Three sibling functions in the SAME repository
that read the same kind of field (headerSize) have a working guard
(x/mlxrunner/model/root.go:144, x/imagegen/manifest/manifest.go:295,
x/server/show.go:383 - all three do
if headerSize > N*1024*1024 { return err } before make()) - the fix
pattern is already known and used elsewhere in this codebase, just not
applied here.
evil_qwen3next_header.bin is the 8-byte little-endian int64 header this
function reads first: value 2^48 (281,474,976,710,656) - large enough to
be a real denial-of-service pressure on heap-arena metadata (positive, so
it avoids the separate int64 sign caveat noted below), while still small
enough to encode in 8 bytes.
Reachability: server/create.go:571 -> convert/convert.go:407
(ConvertModel) -> convert/convert.go:414 (parseTensors) is the sole
call chain into model conversion, triggered by the public HTTP route
POST /api/create (server/routes.go:1891) - reachable without
authentication on unprotected local/private deployments.
Honest limits (not swept under the rug)
- No Go toolchain was available on this host to build ollama and run this live - confidence rests on direct reading of the current source (this function, the three sibling functions with a working guard, and the call chain), not a live crash.
nisint64, notuint64- if the file's 8th byte has the top bit set,nis negative, which causes a recoverable panic (makeslice: cap out of range), not a large allocation. Real DoS requiresnin the positive range shown above, not merely "attacker sets all bits".- Duplicate note: the sibling instance of this exact pattern in
convert/reader_safetensors.go:41-48(parseSafetensors, the safetensors format's own entry point) is ALREADY publicly reported - ollama/ollama issue #17148 and PR #17149 (opened 2026-07-12 by a third party, still open/unmerged as of today) describe exactly that file/function. This report deliberately covers ONLY the separateconvert_qwen3next.goinstance, which is NOT touched by PR #17149's diff and remains unreported.
Impact: Denial of Service - a small (a few bytes) crafted model file with
a qwen3next architecture, imported via the public /api/create endpoint,
can force a large buffer pre-allocation before any content validation.
Suggested fix: Apply the same headerSize > N*1024*1024-style guard already
used in x/mlxrunner/model/root.go, x/imagegen/manifest/manifest.go, and
x/server/show.go to convert_qwen3next.go:226-233 as well.