kcp-fuzzer/src/main.zig

243 lines
7.3 KiB
Zig
Raw Normal View History

2024-09-29 02:15:26 -05:00
const std = @import("std");
const builtin = @import("builtin");
const CircularBuffer = @import("circular-buffer").CircularBuffer;
fn sink(fd: std.posix.fd_t, done: *bool) void {
var buf: [1]u8 = undefined;
var count: usize = 0;
while (true) {
const read = std.posix.read(fd, &buf) catch {
done.* = true;
return;
};
if (read == 0) {
done.* = true;
return;
}
done.* = buf[0] == 0x03;
count +%= read;
}
}
pub fn main() !void {
const fd = try std.posix.open("/dev/tty", .{ .ACCMODE = .RDWR }, 0);
const state = try std.posix.tcgetattr(fd);
var raw = state;
// see termios(3)
raw.iflag.IGNBRK = false;
raw.iflag.BRKINT = false;
raw.iflag.PARMRK = false;
raw.iflag.ISTRIP = false;
raw.iflag.INLCR = false;
raw.iflag.IGNCR = false;
raw.iflag.ICRNL = false;
raw.iflag.IXON = false;
raw.oflag.OPOST = false;
raw.lflag.ECHO = false;
raw.lflag.ECHONL = false;
raw.lflag.ICANON = false;
raw.lflag.ISIG = false;
raw.lflag.IEXTEN = false;
raw.cflag.CSIZE = .CS8;
raw.cflag.PARENB = false;
raw.cc[@intFromEnum(std.posix.V.MIN)] = 1;
raw.cc[@intFromEnum(std.posix.V.TIME)] = 0;
try std.posix.tcsetattr(fd, .FLUSH, raw);
defer {
std.posix.tcsetattr(fd, .FLUSH, state) catch |err| {
std.log.err("couldn't restore terminal: {}", .{err});
};
if (builtin.os.tag != .macos) // closing /dev/tty may block indefinitely on macos
std.posix.close(fd);
}
var done: bool = false;
var thread = try std.Thread.spawn(.{}, sink, .{ fd, &done });
thread.detach();
var cb = CircularBuffer(u20){};
const seed = seed: {
var buf: [4096]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&buf);
var args = try std.process.argsWithAllocator(fba.allocator());
defer args.deinit();
_ = args.next();
while (args.next()) |arg| {
break :seed try std.fmt.parseUnsigned(u64, arg, 0);
}
var seed: u64 = undefined;
try std.posix.getrandom(std.mem.asBytes(&seed));
break :seed seed;
};
var tmp = try std.fs.openDirAbsolute("/tmp", .{});
defer tmp.close();
var prng = std.rand.DefaultPrng.init(seed);
var random = prng.random();
var fn_buf: [std.fs.max_path_bytes]u8 = undefined;
const filename = try std.fmt.bufPrint(
&fn_buf,
"kcp-fuzzer-0x{x:0>16}-0x{x:0>16}.txt",
.{
@abs(std.time.timestamp()),
seed,
},
);
var iteration: usize = 0;
while (!done) : (iteration +%= 1) {
if (iteration & 0x3ff == 0) {
_ = try std.posix.write(fd, ".");
}
var kcp_buf: [512]u8 = undefined;
var kcp_fbs = std.io.fixedBufferStream(&kcp_buf);
var kcp_writer = kcp_fbs.writer();
try kcp_writer.print("\x1b]21", .{});
for (0..random.int(u3)) |_| {
const keys = enum {
2024-09-29 03:46:27 -05:00
palette,
2024-09-29 02:15:26 -05:00
foreground,
background,
selection_background,
selection_foreground,
cursor,
cursor_text,
visual_bell,
transparent_background_color1,
transparent_background_color2,
transparent_background_color3,
transparent_background_color4,
transparent_background_color5,
transparent_background_color6,
transparent_background_color7,
transparent_background_color8,
};
2024-09-29 03:46:27 -05:00
const key = random.enumValue(keys);
switch (key) {
.palette => try kcp_writer.print(";{d}=", .{random.int(u8)}),
else => try kcp_writer.print(";{s}=", .{@tagName(key)}),
}
2024-09-29 02:15:26 -05:00
switch (random.enumValue(enum {
color1,
color2,
color3,
color4,
color5,
color6,
color7,
color8,
color9,
2024-09-29 03:46:27 -05:00
color10,
2024-09-29 02:15:26 -05:00
query,
empty,
})) {
.color1 => try kcp_writer.print(
"rgb:{x:0>1}/{x:0>1}/{x:0>1}",
.{
random.int(u4),
random.int(u4),
random.int(u4),
},
),
.color2 => try kcp_writer.print(
"rgb:{x:0>2}/{x:0>2}/{x:0>2}",
.{
random.int(u8),
random.int(u8),
random.int(u8),
},
),
.color3 => try kcp_writer.print(
"rgb:{x:0>3}/{x:0>3}/{x:0>3}",
.{
random.int(u12),
random.int(u12),
random.int(u12),
},
),
.color4 => try kcp_writer.print(
"rgb:{x:0>4}/{x:0>4}/{x:0>4}",
.{
random.int(u16),
random.int(u16),
random.int(u16),
},
),
.color5 => try kcp_writer.print(
"#{x:0>1}{x:0>1}{x:0>1}",
.{
random.int(u4),
random.int(u4),
random.int(u4),
},
),
.color6 => try kcp_writer.print(
"#{x:0>2}{x:0>2}{x:0>2}",
.{
random.int(u8),
random.int(u8),
random.int(u8),
},
),
.color7 => try kcp_writer.print(
"#{x:0>3}{x:0>3}{x:0>3}",
.{
random.int(u12),
random.int(u12),
random.int(u12),
},
),
.color8 => try kcp_writer.print(
"#{x:0>4}{x:0>4}{x:0>4}",
.{
random.int(u16),
random.int(u16),
random.int(u16),
},
),
.color9 => try kcp_writer.print(
"rgbi:{d:4.2}/{d:4.2}/{d:4.2}",
.{
random.float(f32),
random.float(f32),
random.float(f32),
},
),
2024-09-29 03:46:27 -05:00
.color10 => try kcp_writer.print(
"rgbi:1.00/1.00/1.00",
.{},
),
2024-09-29 02:15:26 -05:00
.query => try kcp_writer.writeByte('?'),
.empty => {},
}
}
try kcp_writer.writeAll("\x1b\\");
const kcp = kcp_fbs.getWritten();
for (kcp) |c| cb.pushByte(c);
var file = try tmp.atomicFile(filename, .{});
defer file.deinit();
try cb.write(file.file.writer());
try file.finish();
_ = try std.posix.write(fd, kcp);
}
}