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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
//! T-COV-95 Generative Falsification: Proptest GGUF Header Assault (PMAT-802)
//!
//! Dr. Popper's directive: "Stop writing manual 'Dark Matter' tests. Instead,
//! implement 'Generative Falsification'—use the `proptest` crate to generate
//! *millions* of valid and invalid GGUF headers. Make the machine find the gap."
//!
//! This module implements:
//! 1. Arbitrary GGUF header generation
//! 2. Byte-Smasher bit-flip fuzzing
//! 3. Dimension permutation testing
//! 4. Metadata type exhaustion
//!
//! Target: 618 missed lines in gguf/loader.rs via algorithmic search
use crate::gguf::{GGUFModel, GGUF_MAGIC, GGUF_VERSION_V3};
use proptest::prelude::*;
// ============================================================================
// GGUF Header Strategy
// ============================================================================
/// Generate arbitrary GGUF magic numbers (valid and invalid)
fn arb_magic() -> impl Strategy<Value = u32> {
prop_oneof![
3 => Just(GGUF_MAGIC), // Valid magic (weighted)
1 => Just(0x46554746), // "FUFG" - almost valid
1 => Just(0x47475546), // "GGUF" wrong endian
1 => Just(0x00000000), // Zero
1 => Just(0xFFFFFFFF), // All ones
1 => any::<u32>(), // Random
]
}
/// Generate arbitrary GGUF versions (valid and invalid)
fn arb_version() -> impl Strategy<Value = u32> {
prop_oneof![
5 => Just(GGUF_VERSION_V3), // Valid v3 (weighted)
1 => Just(0u32), // Invalid v0
1 => Just(1u32), // Legacy v1
1 => Just(2u32), // Legacy v2
1 => Just(4u32), // Future v4
1 => 5u32..255, // Future versions
1 => Just(u32::MAX), // Max version
]
}
/// Generate arbitrary tensor counts
/// Note: Avoid huge values that cause OOM; test bounds checking via validation
fn arb_tensor_count() -> impl Strategy<Value = u64> {
prop_oneof![
3 => 0u64..10, // Small valid (weighted)
2 => 10u64..100, // Medium
1 => 100u64..1000, // Large
1 => Just(0u64), // Zero tensors
1 => Just(10000u64), // Large but bounded
1 => 1000u64..10000, // Large range
]
}
/// Generate arbitrary metadata counts
/// Note: Avoid huge values that cause OOM
fn arb_metadata_count() -> impl Strategy<Value = u64> {
prop_oneof![
4 => 0u64..5, // Small (weighted)
2 => 5u64..20, // Medium
1 => 20u64..100, // Large
1 => Just(1000u64), // Large but bounded
]
}
/// Generate a minimal GGUF header with arbitrary values
fn arb_gguf_header() -> impl Strategy<Value = Vec<u8>> {
(
arb_magic(),
arb_version(),
arb_tensor_count(),
arb_metadata_count(),
)
.prop_map(|(magic, version, tensor_count, metadata_count)| {
let mut data = Vec::with_capacity(24);
data.extend_from_slice(&magic.to_le_bytes());
data.extend_from_slice(&version.to_le_bytes());
data.extend_from_slice(&tensor_count.to_le_bytes());
data.extend_from_slice(&metadata_count.to_le_bytes());
data
})
}
// ============================================================================
// Proptest Cases: Header Fuzzing
// ============================================================================
proptest! {
#![proptest_config(ProptestConfig::with_cases(1000))]
/// Fuzz GGUF headers with arbitrary magic/version/counts
#[test]
fn fuzz_gguf_header(header in arb_gguf_header()) {
// Should not panic regardless of input
let result = GGUFModel::from_bytes(&header);
// Valid magic + version = may succeed if counts are small
// Invalid = should fail gracefully
match result {
Ok(_) => {
// If it succeeded, verify basic invariants
}
Err(_) => {
// Expected for most random inputs
}
}
}
/// Fuzz with valid header but truncated data
#[test]
fn fuzz_truncated_header(
truncate_at in 0usize..24
) {
let mut data = Vec::new();
data.extend_from_slice(&GGUF_MAGIC.to_le_bytes());
data.extend_from_slice(&GGUF_VERSION_V3.to_le_bytes());
data.extend_from_slice(&0u64.to_le_bytes());
data.extend_from_slice(&0u64.to_le_bytes());
data.truncate(truncate_at);
let result = GGUFModel::from_bytes(&data);
// Must not panic
prop_assert!(result.is_err() || truncate_at >= 24);
}
}
// ============================================================================
// Byte-Smasher: Bit-Flip Fuzzing
// ============================================================================
/// Create a valid minimal GGUF and flip bits at specific positions
fn create_valid_minimal_gguf() -> Vec<u8> {
let mut data = Vec::new();
// Valid header
data.extend_from_slice(&GGUF_MAGIC.to_le_bytes());
data.extend_from_slice(&GGUF_VERSION_V3.to_le_bytes());
data.extend_from_slice(&1u64.to_le_bytes()); // 1 tensor
data.extend_from_slice(&0u64.to_le_bytes()); // 0 metadata
// Tensor info
let name = "test_tensor";
data.extend_from_slice(&(name.len() as u64).to_le_bytes());
data.extend_from_slice(name.as_bytes());
data.extend_from_slice(&1u32.to_le_bytes()); // n_dims
data.extend_from_slice(&4u64.to_le_bytes()); // dim[0]
data.extend_from_slice(&0u32.to_le_bytes()); // F32
data.extend_from_slice(&0u64.to_le_bytes()); // offset
// Pad to 32-byte alignment
while data.len() % 32 != 0 {
data.push(0);
}
// Tensor data: 4 f32 values
for i in 0..4 {
data.extend_from_slice(&(i as f32).to_le_bytes());
}
data
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(500))]
/// Byte-Smasher: Flip single bits in magic/version only
/// Note: Limit to magic+version (bytes 0-8) to avoid OOM from corrupted counts
#[test]
fn byte_smasher_single_bit_flip(
byte_idx in 0usize..8,
bit_idx in 0u8..8
) {
let mut data = create_valid_minimal_gguf();
if byte_idx < data.len() {
// Flip the bit
data[byte_idx] ^= 1 << bit_idx;
// Should not panic
let result = GGUFModel::from_bytes(&data);
// Magic byte corruption should fail
if byte_idx < 4 {
prop_assert!(result.is_err());
}
// Version byte corruption (bytes 4-7) should fail for non-v3
// Other corruptions may or may not fail
let _ = result;
}
}
/// Byte-Smasher: Zero out ranges (magic/version only)
#[test]
fn byte_smasher_zero_range(
start in 0usize..8,
len in 1usize..4
) {
let mut data = create_valid_minimal_gguf();
let end = (start + len).min(data.len());
for i in start..end {
data[i] = 0;
}
let result = GGUFModel::from_bytes(&data);
// Should not panic
let _ = result;
}
/// Byte-Smasher: Fill with 0xFF (magic/version only)
#[test]
fn byte_smasher_fill_ff(
start in 0usize..8,
len in 1usize..4
) {
let mut data = create_valid_minimal_gguf();
let end = (start + len).min(data.len());
for i in start..end {
data[i] = 0xFF;
}
let result = GGUFModel::from_bytes(&data);
let _ = result;
}
}
include!("arb_tensor_strategy.rs");