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);
|
|
|
|
}
|
|
|
|
}
|