Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fs/ggml: prevent runtime panics on malformed or corrupt GGUF inputs#14489

Open
maralcbr wants to merge 2 commits intoollama:mainfrom
maralcbr:fix/gguf-string-length-panic
Open

fs/ggml: prevent runtime panics on malformed or corrupt GGUF inputs#14489
maralcbr wants to merge 2 commits intoollama:mainfrom
maralcbr:fix/gguf-string-length-panic

Conversation

@maralcbr
Copy link

@maralcbr maralcbr commented Feb 27, 2026

Summary

readGGUFString, readGGUFArray, and the tensor-info decoder all cast user-supplied uint64 values to int without first validating them. On 64-bit platforms any value larger than math.MaxInt64 wraps to a negative integer, which then causes make() to panic at runtime with:

panic: runtime error: makeslice: len out of range
    github.com/ollama/ollama/fs/ggml/gguf.go:361 +0xc5
github.com/ollama/ollama/fs/ggml.(*gguf).Decode ...
    github.com/ollama/ollama/fs/ggml/gguf.go:195 +0x45a

This was reproduced loading multi-shard Unsloth UD-Q3_K_XL GGUFs that contain mxfp4 tensors: prior to the separation of tensor-info reads from size-validation seeks (now in a dedicated post-processing loop), a misaligned file reader could land on raw weight data whose bytes decoded as an enormous string length, crashing the entire Ollama server process instead of returning a descriptive error.

Changes

  • readGGUFString: validate the raw uint64 length before casting to int; return a descriptive error if it exceeds 1 GiB (far beyond any legitimate GGUF string).
  • readGGUFArray: validate the element count before casting to int; return an error if it exceeds 2^32.
  • gguf.Decode tensor loop: validate that dims does not exceed GGML_MAX_DIMS (4) before allocating the shape slice, matching the llama.cpp spec.

All three fixes convert would-be runtime panics into well-formed errors that propagate up cleanly.

Tests

Three new sub-tests added to TestWriteGGUF:

  • oversized_string_length_returns_error — covers both maxUint64 and maxInt64+1 (the overflow boundary), and just over the 1 GiB cap
  • oversized_array_length_returns_errormaxUint64 element count
  • too_many_tensor_dims_returns_errordims = 5 > GGML_MAX_DIMS

Test plan

  • go test ./fs/ggml/... passes (all new sub-tests return errors rather than panicking)
  • Existing TestWriteGGUF round-trip tests still pass
  • Smoke test with an Unsloth UD-Q3_K_XL merged GGUF: ollama create completes without server panic

readGGUFString, readGGUFArray, and the tensor-info decoder all cast
user-supplied uint64 values to int without first validating them.  On
64-bit platforms any value larger than math.MaxInt64 wraps to a
negative integer, which then causes make() to panic at runtime with
"makeslice: len out of range".

This was observed in the wild when loading multi-shard Unsloth
UD-Q3_K_XL GGUFs that contain mxfp4 tensors: a misaligned reader
(present in prior versions where size-validation seeks were interleaved
with tensor-info reads) could land on weight data whose bytes decoded as
a huge string length, crashing the server instead of returning an error.

Fix by:
- Checking the raw uint64 length in readGGUFString before casting and
  returning a descriptive error if it exceeds 1 GiB.
- Checking the array element count in readGGUFArray before casting and
  returning an error if it exceeds 2^32.
- Validating that a tensor's dims field does not exceed GGML_MAX_DIMS (4)
  before allocating the shape slice.

Tests added for all three cases to ensure errors are returned rather
than panics produced.

Made-with: Cursor
…ruptInputs

The three regression tests added in the previous commit were nested inside
TestWriteGGUF, which tests write+round-trip behavior.  These tests have
nothing to do with writing; they verify that Decode returns a descriptive
error (rather than panicking) when given malformed inputs.

Move them — along with their writeMinimalGGUF/writeKVString helpers — into
a new top-level TestDecodeGGUFCorruptInputs function.  Add a comment
explaining that the oversized-string and oversized-array cases would have
triggered a "makeslice: len out of range" runtime panic on unpatched code
(int(math.MaxUint64) == -1, make([]T,-1) panics).

Made-with: Cursor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant