mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-09-14 18:01:58 +00:00
67 lines
2.2 KiB
Zig
67 lines
2.2 KiB
Zig
const builtin = @import("builtin");
|
|
const std = @import("std");
|
|
const ghostty_vt = @import("ghostty-vt");
|
|
const mem = @import("mem.zig");
|
|
const Terminal = ghostty_vt.Terminal;
|
|
const TerminalStream = ghostty_vt.TerminalStream;
|
|
|
|
/// Use a single global allocator for simplicity and to avoid heap
|
|
/// allocation overhead in the fuzzer. The allocator is backed by a fixed
|
|
/// buffer, and every fuzz input resets the bump pointer to the start.
|
|
var fuzz_alloc: mem.FuzzAllocator(64 * 1024 * 1024) = .{};
|
|
|
|
pub export fn zig_fuzz_init() callconv(.c) void {
|
|
fuzz_alloc.init();
|
|
}
|
|
|
|
pub export fn zig_fuzz_test(
|
|
buf: [*]const u8,
|
|
len: usize,
|
|
) callconv(.c) void {
|
|
// Do not test zero-length input paths.
|
|
if (len == 0) return;
|
|
|
|
fuzz_alloc.reset();
|
|
const alloc = fuzz_alloc.allocator();
|
|
const input = buf[0..len];
|
|
|
|
const argv0 = "ghostty-fuzz";
|
|
const argv0_windows = argv0_windows: {
|
|
var argv0_windows_buf: [std.unicode.calcUtf16LeLen(argv0) catch unreachable]u16 = undefined;
|
|
_ = std.unicode.utf8ToUtf16Le(&argv0_windows_buf, argv0) catch unreachable;
|
|
break :argv0_windows argv0_windows_buf;
|
|
};
|
|
var threaded: std.Io.Threaded = .init(alloc, .{
|
|
.argv0 = .init(.{ .vector = if (builtin.target.os.tag == .windows)
|
|
&argv0_windows
|
|
else
|
|
&.{argv0} }),
|
|
});
|
|
defer threaded.deinit();
|
|
|
|
// Allocate a terminal; if we run out of fixed-buffer space just
|
|
// skip this input (not a bug, just a very large allocation).
|
|
var t = Terminal.init(threaded.io(), alloc, .{
|
|
.cols = 80,
|
|
.rows = 24,
|
|
.max_scrollback_bytes = 100,
|
|
}) catch return;
|
|
defer t.deinit(alloc);
|
|
|
|
var stream: TerminalStream = t.vtStream();
|
|
defer stream.deinit();
|
|
|
|
// Use the first byte to decide between the scalar and slice paths
|
|
// so both code paths get exercised by the fuzzer.
|
|
const mode = input[0];
|
|
const data = input[1..];
|
|
|
|
if (mode & 1 == 0) {
|
|
// Slice path — exercises SIMD fast-path if enabled
|
|
stream.nextSlice(data);
|
|
} else {
|
|
// Scalar path — exercises byte-at-a-time UTF-8 decoding
|
|
for (data) |byte| stream.next(byte);
|
|
}
|
|
}
|