feature. See also
. The project being documented here (as the example) is the Zig library itself.
Compress.testFuzzedCompressInput
fn testFuzzedCompressInput(fbufs: *const [2][65536]u8, smith: *std.testing.Smith) !void
File
Code
fn testFuzzedCompressInput(fbufs: *const [2][65536]u8, smith: *std.testing.Smith) !void {
@disableInstrumentation();
const container = smith.value(flate.Container);
const good = smith.valueRangeAtMost(u16, 3, 258);
const nice = smith.valueRangeAtMost(u16, 3, 258);
const lazy = smith.valueRangeAtMost(u16, 3, nice);
const chain = smith.valueWeighted(u16, &.{
.rangeAtMost(u16, if (good <= lazy) 4 else 1, 255, 65536),
.rangeAtMost(u16, 256, 4095, 256),
.rangeAtMost(u16, 4096, 32767 + 256, 1),
});
var expected_hash: flate.Container.Hasher = .init(container);
var expected_size: u32 = 0;
var flate_buf: [128 * 1024]u8 = undefined;
var flate_w: Writer = .fixed(&flate_buf);
var deflate_buf: [flate.max_window_len * 2]u8 = undefined;
const bufsize = smith.valueRangeAtMost(u32, flate.max_window_len, @intCast(deflate_buf.len));
var deflate_w = try Compress.init(&flate_w, deflate_buf[0..bufsize], container, .{
.good = good,
.nice = nice,
.lazy = lazy,
.chain = chain,
});
var max_output: usize = 32;
while (!smith.eosWeightedSimple(7, 1)) {
const buffered = deflate_w.writer.buffered();
var copy_buf: [512]u8 = undefined;
const bytes = bytes: switch (smith.valueRangeAtMost(
u2,
@intFromBool(buffered.len == 0),
3,
)) {
0 => {
const start = smith.valueRangeLessThan(u32, 0, @intCast(buffered.len));
const from = buffered[start..];
const len = smith.valueRangeAtMost(u16, 1, copy_buf.len);
const history_bytes = from[0..@min(from.len, len)];
@memcpy(copy_buf[0..history_bytes.len], history_bytes);
const repeat_len = len - history_bytes.len;
for (
copy_buf[history_bytes.len..][0..repeat_len],
copy_buf[0..repeat_len],
) |*next, prev| {
next.* = prev;
}
break :bytes copy_buf[0..len];
},
1 => {
const fbuf = &fbufs[
smith.valueWeighted(u1, &.{
.value(FreqBufIndex, .gradient, 3),
.value(FreqBufIndex, .random, 1),
})
];
const len = smith.valueRangeAtMost(u32, 1, fbuf.len);
const off = smith.valueRangeAtMost(u32, 0, @intCast(fbuf.len - len));
break :bytes fbuf[off..][0..len];
},
2 => {
const rebaseable = bufsize - rebase_reserved_capacity;
const capacity = smith.valueRangeAtMost(u32, 1, rebaseable - rebase_min_preserve);
const preserve = smith.valueRangeAtMost(u32, 0, rebaseable - capacity);
const failed = deflate_w.writer.rebase(preserve, capacity);
if (flate_w.buffered().len > max_output) return error.OverheadTooLarge;
failed catch return;
continue;
},
3 => {
max_output += 8;
const failed = deflate_w.writer.flush();
if (flate_w.buffered().len > max_output) return error.OverheadTooLarge;
failed catch return;
continue;
},
};
// gaurauntee it writes store blocks when optimal. This comes from taking less than 32
// bytes to write an optimal dynamic block header of mostly bitlen 8 codes and the end
// of block literal plus `(65536 / 256) / 8`, which is is the maximum number of extra
// bytes from bitlen 9 codes.
max_output += bytes.len + ((bytes.len + flate_buf.len - 1) / block_tokens) * 64;
const failed = deflate_w.writer.writeAll(bytes);
if (flate_w.buffered().len > max_output) return error.OverheadTooLarge;
failed catch return;
expected_hash.update(bytes);
expected_size += @intCast(bytes.len);
}
const failed = deflate_w.finish();
if (flate_w.buffered().len > max_output) return error.OverheadTooLarge;
failed catch return;
try testingCheckDecompressedMatches(flate_w.buffered(), expected_size, expected_hash);
}