| # GGUF metadata array parser DoS |
|
|
| This PoC demonstrates a small GGUF file that causes `gguf.GGUFReader` to spend unbounded CPU time parsing malformed metadata. |
|
|
| The crafted file declares a metadata field named `tokenizer.ggml.tokens` as a `GGUFValueType.ARRAY` with element type `UINT8` and array length `50,000,000`, but the file intentionally omits the array payload. |
|
|
| `GGUFReader._get_field_parts()` trusts the declared length and iterates `range(alen[0])` before validating that the payload exists. A 69-byte file therefore causes the parser to hang past the verification timeout, while a control file with array length `4` parses immediately. |
|
|
| ## Files |
|
|
| - `gguf_huge_array_metadata_dos.gguf`: malicious PoC file |
| - `control_small_array.gguf`: control GGUF file with small array length |
| - `build_and_verify.py`: rebuilds the files and verifies the parser behavior |
| - `verify_report.json`: local verification output |
|
|
| ## Reproduction |
|
|
| Install dependencies: |
|
|
| ```bash |
| pip install gguf modelscan |
| ``` |
|
|
| Run: |
|
|
| ```bash |
| python build_and_verify.py |
| ``` |
|
|
| Expected result: |
|
|
| - `control_parse.timeout=false` |
| - `control_parse.stdout` starts with `OK` |
| - `malicious_parse.timeout=true` |
| - ModelScan reports `total_issues=0` and `total_scanned=0` for the PoC file |
|
|
| ## Impact |
|
|
| Any service that accepts untrusted GGUF files and parses metadata with `gguf.GGUFReader` can be forced into CPU and memory exhaustion using a very small file. |
|
|