GraySoft
Projects Models Compare Cloud benchmarks FAQ Download guIDE →
Model Intelligence Sheet

ChristianTeroerde/ovgenai-gguf-q4k-oob-poc overview

PoC: heap out of bounds write in OpenVINO GenAI's GGUF Q4 K dequantizer Security proof of concept for a CWE 787 heap OOB write triggered when openvinotoolkit/o…

ggufsecurity-pocopenvinolicense:mitendpoints_compatibleregion:us

Runs locally from ~0.0 MB disk (4 GB VRAM class GPUs with llama.cpp / guIDE).

Downloads
0
Likes
0
Pipeline

Repository Files & Downloads

1 GGUF files detected
Direct downloads for local inference
FileTypeQuantizationSizeLink
crafted.ggufGGUFGGUF0.0 MBDownload

Model Details

Model IDChristianTeroerde/ovgenai-gguf-q4k-oob-poc
AuthorChristianTeroerde
Pipeline
Licensemit
Base model
Last modified2026-06-18T07:39:27.000Z

Model README

---

license: mit

tags:

  • security-poc
  • gguf
  • openvino

---

PoC: heap out-of-bounds write in OpenVINO GenAI's GGUF Q4_K dequantizer

Security proof-of-concept for a CWE-787 heap OOB-write triggered when

openvinotoolkit/openvino.genai

loads a crafted .gguf model through its direct-GGUF preview loader.

This repo exists only to reproduce the bug for the maintainer / triager. The

crafted file is a benign 672-byte PoC — it contains no payload; it merely

makes the dequantizer write a few bytes past freshly-allocated heap buffers so

the overrun is observable under valgrind.

Affected

  • Component: openvino.genai direct-GGUF reader — src/cpp/src/gguf_utils/gguf_quants.cpp

(gguf_load_quantized / extract_q4_k_data). Independent of llama.cpp/ggml.

  • Versions: openvino-genai >= 2025.2.0.0 (the GGUF loader's first release), verified at

2025.2.0.0 / 2025.4.0.0 / 2026.2.1.0 and on current master. Not present in <= 2025.1.0.0.

Root cause (one line)

gguf_load_quantized allocates the dequant destination buffers from the tensor's

last dim guarded only by last_dim % 32 == 0 (the Q4_K sub-block size), but

extract_q4_k_data writes a full 256-weight super-block (8 f16 scales + 8 f16

biases + 128 weight-bytes) per 144 input bytes. A tensor with last_dim = 224

(224 % 32 == 0 but 224 % 256 != 0) passes the guard yet overruns scales/biases

by +2 bytes and weights by +16 bytes per affected tensor.

Reproduce

# needs docker (pulls python:3.11, pip-installs the stock wheel, runs under valgrind)
OVGENAI_VER=2026.2.1.0 ./run.sh

run.sh loads crafted.gguf via openvino_genai.LLMPipeline("crafted.gguf", "CPU")

under valgrind --tool=memcheck --error-exitcode=99. Expected:

==…== Invalid write of size 2  … extract_q4_k_data … gguf_load_quantized
==…==   Address … is 0 bytes after a block of size 14 alloc'd     <-- scales (7 f16), wrote scales[7]
==…== Invalid write of size 8  … unpack_256_4 … extract_q4_k_data
==…==   Address … is 0 bytes after a block of size 112 alloc'd    <-- weights (28 u32 = 112 B), wrote [112..127]

(docker exits 99 = valgrind found the OOB-writes.) The full captured run is in

valgrind-full.log; a trimmed transcript is in poc-evidence.txt.

Files

  • crafted.gguf — the 672-byte PoC model (single Q4_K *.weight, declared shape [224], 144 B data + minimal KV).
  • build_gguf.py — regenerates crafted.gguf (injects the [224] Q4_K tensor past the gguf lib's own 256-alignment check).
  • load_crafted.py — the loader called inside the container.
  • run.sh — one-command docker + valgrind reproduction.
  • valgrind-full.log / poc-evidence.txt — captured evidence.

Suggested fix

Guard the super-block size for K-quants (last_dim % 256 == 0 for Q4_K/Q6_K),

or size the destination buffers from n_super_block (the actual write count) rather

than last_dim / weights_per_block.

Run ChristianTeroerde/ovgenai-gguf-q4k-oob-poc with guIDE

Download guIDE — the AI-native code editor with local LLM inference and 69 built-in tools.

Download guIDE → · Browse 524k+ models · Compare models

Source: Hugging Face · Compare models