From e081a4abb4a9212ca99a797fa4497c08b1a3e5f3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 1 Mar 2026 13:46:13 -0800 Subject: [PATCH] fuzz/vt-stream --- src/lib_vt.zig | 2 + test/fuzz-libghostty/.gitattributes | 3 + test/fuzz-libghostty/AGENTS.md | 14 +-- test/fuzz-libghostty/README.md | 76 +++++++++-------- test/fuzz-libghostty/build.zig | 80 ++++++++++-------- .../vt-stream-initial/01-plain-text-slice | Bin 0 -> 16 bytes .../vt-stream-initial/02-plain-text-scalar | 1 + .../vt-stream-initial/03-csi-cursor-sgr | Bin 0 -> 24 bytes .../corpus/vt-stream-initial/04-csi-erase | Bin 0 -> 15 bytes .../corpus/vt-stream-initial/05-osc-title-bel | Bin 0 -> 14 bytes .../corpus/vt-stream-initial/06-osc-title-st | Bin 0 -> 15 bytes .../corpus/vt-stream-initial/07-dcs-decrqss | 1 + .../corpus/vt-stream-initial/08-apc | Bin 0 -> 20 bytes .../vt-stream-initial/09-mixed-text-csi | 2 + .../corpus/vt-stream-initial/10-sgr-256-rgb | Bin 0 -> 42 bytes .../vt-stream-initial/11-utf8-multibyte | Bin 0 -> 10 bytes .../vt-stream-initial/12-malformed-utf8 | 1 + .../vt-stream-initial/13-incomplete-csi | Bin 0 -> 9 bytes .../corpus/vt-stream-initial/14-decset-decrst | Bin 0 -> 29 bytes .../corpus/vt-stream-initial/15-scroll-region | 1 + .../corpus/vt-stream-initial/16-c1-controls | Bin 0 -> 15 bytes .../corpus/vt-stream-initial/17-tab-backspace | Bin 0 -> 9 bytes .../corpus/vt-stream-initial/18-insert-delete | 1 + .../corpus/vt-stream-initial/19-many-params | Bin 0 -> 42 bytes .../corpus/vt-stream-initial/20-csi-subparams | Bin 0 -> 27 bytes .../corpus/vt-stream-initial/21-osc-hyperlink | Bin 0 -> 39 bytes .../corpus/vt-stream-initial/22-osc-clipboard | 1 + .../corpus/vt-stream-initial/23-empty | Bin 0 -> 1 bytes .../corpus/vt-stream-initial/24-esc-misc | 1 + .../src/{lib.zig => fuzz_vt_parser.zig} | 0 test/fuzz-libghostty/src/fuzz_vt_stream.zig | 71 ++++++++++++++++ 31 files changed, 178 insertions(+), 77 deletions(-) create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/01-plain-text-slice create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/02-plain-text-scalar create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/03-csi-cursor-sgr create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/04-csi-erase create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/05-osc-title-bel create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/06-osc-title-st create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/07-dcs-decrqss create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/08-apc create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/09-mixed-text-csi create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/10-sgr-256-rgb create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/11-utf8-multibyte create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/12-malformed-utf8 create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/13-incomplete-csi create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/14-decset-decrst create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/15-scroll-region create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/16-c1-controls create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/17-tab-backspace create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/18-insert-delete create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/19-many-params create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/20-csi-subparams create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/21-osc-hyperlink create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/22-osc-clipboard create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/23-empty create mode 100644 test/fuzz-libghostty/corpus/vt-stream-initial/24-esc-misc rename test/fuzz-libghostty/src/{lib.zig => fuzz_vt_parser.zig} (100%) create mode 100644 test/fuzz-libghostty/src/fuzz_vt_stream.zig diff --git a/src/lib_vt.zig b/src/lib_vt.zig index 251faa0a4..426660621 100644 --- a/src/lib_vt.zig +++ b/src/lib_vt.zig @@ -59,6 +59,8 @@ pub const Style = terminal.Style; pub const Terminal = terminal.Terminal; pub const Stream = terminal.Stream; pub const StreamAction = terminal.StreamAction; +pub const ReadonlyStream = terminal.ReadonlyStream; +pub const ReadonlyHandler = terminal.ReadonlyHandler; pub const Cursor = Screen.Cursor; pub const CursorStyle = Screen.CursorStyle; pub const CursorStyleReq = terminal.CursorStyle; diff --git a/test/fuzz-libghostty/.gitattributes b/test/fuzz-libghostty/.gitattributes index de57ad9a7..50dce46fd 100644 --- a/test/fuzz-libghostty/.gitattributes +++ b/test/fuzz-libghostty/.gitattributes @@ -1,6 +1,9 @@ # Hand-written seed corpus: binary files, track as-is corpus/initial/** binary +corpus/vt-stream-initial/** binary # Generated/minimized corpora: binary, mark as generated corpus/vt-parser-cmin/** binary linguist-generated=true corpus/vt-parser-min/** binary linguist-generated=true +corpus/vt-stream-cmin/** binary linguist-generated=true +corpus/vt-stream-min/** binary linguist-generated=true diff --git a/test/fuzz-libghostty/AGENTS.md b/test/fuzz-libghostty/AGENTS.md index 042173a75..daafdb887 100644 --- a/test/fuzz-libghostty/AGENTS.md +++ b/test/fuzz-libghostty/AGENTS.md @@ -1,14 +1,14 @@ # AFL++ Fuzzer for Libghostty -- `ghostty-fuzz` is a binary built with `afl-cc` -- Build `ghostty-fuzz` with `zig build` +- Fuzz targets: `fuzz-vt-parser` and `fuzz-vt-stream` +- Build all targets with `zig build` - After running `afl-cmin`/`afl-tmin`, run `corpus/sanitize-filenames.sh` before committing to replace colons with underscores (colons are invalid on Windows NTFS). ## Important: stdin-based input -The instrumented binary (`afl.c` harness) reads fuzz input from **stdin**, +The instrumented binaries (`afl.c` harness) read fuzz input from **stdin**, not from a file argument. This affects how you invoke AFL++ tools: - **`afl-fuzz`**: Uses shared-memory fuzzing automatically; `@@` works @@ -16,7 +16,7 @@ not from a file argument. This affects how you invoke AFL++ tools: - **`afl-showmap`**: Must pipe input via stdin, **not** `@@`: ```sh - cat testcase | afl-showmap -o map.txt -- zig-out/bin/ghostty-fuzz + cat testcase | afl-showmap -o map.txt -- zig-out/bin/fuzz-vt-stream ``` - **`afl-cmin`**: Do **not** use `@@`. Requires `AFL_NO_FORKSRV=1` with @@ -24,14 +24,14 @@ not from a file argument. This affects how you invoke AFL++ tools: ```sh AFL_NO_FORKSRV=1 /opt/homebrew/Cellar/afl++/4.35c/libexec/afl-cmin.bash \ - -i afl-out/default/queue -o corpus/vt-parser-cmin \ - -- zig-out/bin/ghostty-fuzz + -i afl-out/fuzz-vt-stream/default/queue -o corpus/vt-stream-cmin \ + -- zig-out/bin/fuzz-vt-stream ``` - **`afl-tmin`**: Also requires `AFL_NO_FORKSRV=1`, no `@@`: ```sh - AFL_NO_FORKSRV=1 afl-tmin -i -o -- zig-out/bin/ghostty-fuzz + AFL_NO_FORKSRV=1 afl-tmin -i -o -- zig-out/bin/fuzz-vt-stream ``` If you pass `@@` or a filename argument, `afl-showmap`/`afl-cmin`/`afl-tmin` diff --git a/test/fuzz-libghostty/README.md b/test/fuzz-libghostty/README.md index 64dccd066..4bf9d6676 100644 --- a/test/fuzz-libghostty/README.md +++ b/test/fuzz-libghostty/README.md @@ -1,9 +1,19 @@ # AFL++ Fuzzer for Libghostty -This directory contains an [AFL++](https://aflplus.plus/) fuzzing harness for -libghostty-vt (Zig module). At the time of writing this README, it only -fuzzes the VT parser, but it can be extended to cover other components of -libghostty as well. +This directory contains [AFL++](https://aflplus.plus/) fuzzing harnesses for +libghostty-vt (Zig module). + +## Fuzz Targets + +| Target | Binary | Description | +| ------------------ | ------------------ | ------------------------------------------------------- | +| `fuzz-vt-parser` | `fuzz-vt-parser` | VT parser only (`Parser.next` byte-at-a-time) | +| `fuzz-vt-stream` | `fuzz-vt-stream` | Full terminal stream (`nextSlice` + `next` via handler) | + +The stream target creates a small `Terminal` and exercises the readonly +`Stream` handler, covering printing, CSI dispatch, OSC, DCS, SGR, cursor +movement, scrolling regions, and more. The first byte of each input selects +between the slice path (SIMD fast-path) and the scalar path. ## Prerequisites @@ -21,43 +31,39 @@ From this directory (`test/fuzz-libghostty`): zig build ``` -This compiles a Zig static library (with the fuzz harness in `src/lib.zig`), -emits LLVM bitcode, then links it with `src/main.c` using `afl-cc` to produce -the instrumented binary at `zig-out/bin/ghostty-fuzz`. +This compiles Zig static libraries for each fuzz target, emits LLVM bitcode, +then links each with `afl.c` using `afl-cc` to produce instrumented binaries +at `zig-out/bin/fuzz-vt-parser` and `zig-out/bin/fuzz-vt-stream`. ## Running the Fuzzer -The build system has a convenience step that invokes `afl-fuzz` with the -correct arguments: +Each target has its own run step: ```sh -zig build run +zig build run-fuzz-vt-parser # Run the VT parser fuzzer +zig build run-fuzz-vt-stream # Run the VT stream fuzzer +zig build run # Alias for run-fuzz-vt-parser ``` -This is equivalent to: +Or invoke `afl-fuzz` directly: ```sh -afl-fuzz -i corpus/initial -o afl-out -- zig-out/bin/ghostty-fuzz @@ +afl-fuzz -i corpus/vt-stream-initial -o afl-out/fuzz-vt-stream -- zig-out/bin/fuzz-vt-stream @@ ``` -You may want to run `afl-fuzz` directly with different options -for your own experimentation. - The fuzzer runs indefinitely. Let it run for as long as you like; meaningful coverage is usually reached within a few hours, but longer runs can find deeper bugs. Press `ctrl+c` to stop the fuzzer when you're done. ## Finding Crashes and Hangs -After (or during) a run, results are written to `afl-out/default/`: +After (or during) a run, results are written to `afl-out//default/`: ``` - -afl-out/default/ +afl-out/fuzz-vt-stream/default/ ├── crashes/ # Inputs that triggered crashes -├── hangs/ # Inputs that triggered hangs/timeouts -└── queue/ # All interesting inputs (the evolved corpus) - +├── hangs/ # Inputs that triggered hangs/timeouts +└── queue/ # All interesting inputs (the evolved corpus) ``` Each file in `crashes/` or `hangs/` is a raw byte file that triggered the @@ -69,12 +75,12 @@ issue. The filename encodes metadata about how it was found (e.g. Replay any crashing input by piping it into the harness: ```sh -cat afl-out/default/crashes/ | zig-out/bin/ghostty-fuzz +cat afl-out/fuzz-vt-stream/default/crashes/ | zig-out/bin/fuzz-vt-stream ``` ## Corpus Management -After a fuzzing run, the queue in `afl-out/default/queue/` typically +After a fuzzing run, the queue in `afl-out//default/queue/` typically contains many redundant inputs. Use `afl-cmin` to find the smallest subset that preserves full edge coverage, and `afl-tmin` to shrink individual test cases. @@ -90,9 +96,9 @@ Reduce the evolved queue to a minimal set covering all discovered edges: ```sh AFL_NO_FORKSRV=1 afl-cmin.bash \ - -i afl-out/default/queue \ - -o corpus/vt-parser-cmin \ - -- zig-out/bin/ghostty-fuzz + -i afl-out/fuzz-vt-stream/default/queue \ + -o corpus/vt-stream-cmin \ + -- zig-out/bin/fuzz-vt-stream ``` `AFL_NO_FORKSRV=1` is required because the Python `afl-cmin` wrapper has @@ -105,12 +111,12 @@ Shrink each file in the minimized corpus to the smallest input that preserves its unique coverage: ```sh -mkdir -p corpus/vt-parser-min -for f in corpus/vt-parser-cmin/*; do +mkdir -p corpus/vt-stream-min +for f in corpus/vt-stream-cmin/*; do AFL_NO_FORKSRV=1 afl-tmin \ -i "$f" \ - -o "corpus/vt-parser-min/$(basename "$f")" \ - -- zig-out/bin/ghostty-fuzz + -o "corpus/vt-stream-min/$(basename "$f")" \ + -- zig-out/bin/fuzz-vt-stream done ``` @@ -130,8 +136,8 @@ rename the output files to replace colons with underscores before committing: ### Corpus directories -| Directory | Contents | -| ------------------------ | ----------------------------------------------- | -| `corpus/initial/` | Hand-written seed inputs for `afl-fuzz -i` | -| `corpus/vt-parser-cmin/` | Output of `afl-cmin` (edge-deduplicated corpus) | -| `corpus/vt-parser-min/` | Output of `afl-tmin` (individually minimized) | +| Directory | Contents | +| -------------------------- | ----------------------------------------------- | +| `corpus/initial/` | Hand-written seed inputs for vt-parser | +| `corpus/vt-parser-cmin/` | Output of `afl-cmin` (edge-deduplicated corpus) | +| `corpus/vt-stream-initial/`| Hand-written seed inputs for vt-stream | diff --git a/test/fuzz-libghostty/build.zig b/test/fuzz-libghostty/build.zig index bd6b42615..037f5cae8 100644 --- a/test/fuzz-libghostty/build.zig +++ b/test/fuzz-libghostty/build.zig @@ -1,59 +1,69 @@ const std = @import("std"); const afl = @import("afl"); +const FuzzTarget = struct { + name: []const u8, + source: []const u8, + corpus: []const u8, +}; + +const fuzz_targets = [_]FuzzTarget{ + .{ + .name = "fuzz-vt-parser", + .source = "src/fuzz_vt_parser.zig", + .corpus = "corpus/vt-parser-cmin", + }, + .{ + .name = "fuzz-vt-stream", + .source = "src/fuzz_vt_stream.zig", + .corpus = "corpus/vt-stream-initial", + }, +}; + pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const run_step = b.step("run", "Run the fuzzer with afl-fuzz"); + const run_step = b.step("run", "Run the default fuzzer (vt-parser) with afl-fuzz"); + + const ghostty_dep = b.lazyDependency("ghostty", .{ + .simd = false, + }); + + for (fuzz_targets, 0..) |fuzz, i| { + const target_run_step = b.step( + b.fmt("run-{s}", .{fuzz.name}), + b.fmt("Run {s} with afl-fuzz", .{fuzz.name}), + ); - // Create the C ABI library from Zig source that exports the - // API that the `afl-cc` main.c entrypoint can call into. This - // lets us just use standard `afl-cc` to fuzz test our library without - // needing to write any Zig-specific fuzzing harnesses. - const lib = lib: { - // Zig module const lib_mod = b.createModule(.{ - .root_source_file = b.path("src/lib.zig"), + .root_source_file = b.path(fuzz.source), .target = target, .optimize = optimize, }); - if (b.lazyDependency("ghostty", .{ - .simd = false, - })) |dep| { - lib_mod.addImport( - "ghostty-vt", - dep.module("ghostty-vt"), - ); + if (ghostty_dep) |dep| { + lib_mod.addImport("ghostty-vt", dep.module("ghostty-vt")); } - // C lib const lib = b.addLibrary(.{ - .name = "ghostty-fuzz", + .name = fuzz.name, .root_module = lib_mod, }); - - // Required to build properly with afl-cc lib.root_module.stack_check = false; lib.root_module.fuzz = true; - break :lib lib; - }; + const exe = afl.addInstrumentedExe(b, lib); - // Build a C entrypoint with afl-cc that links against the generated - // static Zig library. afl-cc is expected to be on the PATH. - const exe = afl.addInstrumentedExe(b, lib); + const run = afl.addFuzzerRun(b, exe, b.path(fuzz.corpus), b.path(b.fmt("afl-out/{s}", .{fuzz.name}))); - // Runner to simplify running afl-fuzz. - // Use the cmin corpus (edge-deduplicated from prior runs) so that each - // fuzzing session starts from full coverage. Switch to "corpus/initial" - // if you don't have a cmin corpus yet. - const run = afl.addFuzzerRun(b, exe, b.path("corpus/vt-parser-cmin"), b.path("afl-out")); + b.installArtifact(lib); + const exe_install = b.addInstallBinFile(exe, fuzz.name); + b.getInstallStep().dependOn(&exe_install.step); - // Install - b.installArtifact(lib); - const exe_install = b.addInstallBinFile(exe, "ghostty-fuzz"); - b.getInstallStep().dependOn(&exe_install.step); + target_run_step.dependOn(&run.step); - // Run - run_step.dependOn(&run.step); + // Default `zig build run` runs the first target (vt-parser) + if (i == 0) { + run_step.dependOn(&run.step); + } + } } diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/01-plain-text-slice b/test/fuzz-libghostty/corpus/vt-stream-initial/01-plain-text-slice new file mode 100644 index 0000000000000000000000000000000000000000..be111345f7d57c8d0716f48c225e956433895732 GIT binary patch literal 16 XcmZSZNX^N~*HH-1FUm<#jNHa5&HN==cDHpm44NoEF? literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/04-csi-erase b/test/fuzz-libghostty/corpus/vt-stream-initial/04-csi-erase new file mode 100644 index 0000000000000000000000000000000000000000..ce1416a30eeed4b5216ebab9aceb68d74fb727f9 GIT binary patch literal 15 WcmZROjyCd=j`om__Rh)7O9cQLu>=|b literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/05-osc-title-bel b/test/fuzz-libghostty/corpus/vt-stream-initial/05-osc-title-bel new file mode 100644 index 0000000000000000000000000000000000000000..c580d9151585a4dd2760ec161cc0358b592b13b2 GIT binary patch literal 14 VcmZROjy16MtyBofEXhe_2LKsv1JeKi literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/06-osc-title-st b/test/fuzz-libghostty/corpus/vt-stream-initial/06-osc-title-st new file mode 100644 index 0000000000000000000000000000000000000000..792485f09d018b8acf4ec9eabf5df867d9919306 GIT binary patch literal 15 WcmZROjy16MtyBofEXhfgjsXB2#RNkD literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/07-dcs-decrqss b/test/fuzz-libghostty/corpus/vt-stream-initial/07-dcs-decrqss new file mode 100644 index 000000000..9e9a56b30 --- /dev/null +++ b/test/fuzz-libghostty/corpus/vt-stream-initial/07-dcs-decrqss @@ -0,0 +1 @@ +P$q"p\ \ No newline at end of file diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/08-apc b/test/fuzz-libghostty/corpus/vt-stream-initial/08-apc new file mode 100644 index 0000000000000000000000000000000000000000..7972be99c7b607bdd7cb71287fb85b1d97e38a0c GIT binary patch literal 20 bcmZROj(1P9H8e2LDYiA#DYG@SmW}}cFbV|4 literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/09-mixed-text-csi b/test/fuzz-libghostty/corpus/vt-stream-initial/09-mixed-text-csi new file mode 100644 index 000000000..a01d1ca9e --- /dev/null +++ b/test/fuzz-libghostty/corpus/vt-stream-initial/09-mixed-text-csi @@ -0,0 +1,2 @@ +ABCDhello +world \ No newline at end of file diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/10-sgr-256-rgb b/test/fuzz-libghostty/corpus/vt-stream-initial/10-sgr-256-rgb new file mode 100644 index 0000000000000000000000000000000000000000..5439f26a41b81520f20a80efd4d148f72ab8d4e0 GIT binary patch literal 42 xcmZROjyATiHnldiG|MeYO_7c^v9LC>Hn27_HMKU#O)pAK%~ME9myR~b1pwc63rhe1 literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/11-utf8-multibyte b/test/fuzz-libghostty/corpus/vt-stream-initial/11-utf8-multibyte new file mode 100644 index 0000000000000000000000000000000000000000..73c1225943275628cedfe4694a6fcc8fc31d3a05 GIT binary patch literal 10 ScmZQLyz4&5@3_H#9J@%mDL1B#4&-0AgJR=Kufz literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/15-scroll-region b/test/fuzz-libghostty/corpus/vt-stream-initial/15-scroll-region new file mode 100644 index 000000000..79554c7c9 --- /dev/null +++ b/test/fuzz-libghostty/corpus/vt-stream-initial/15-scroll-region @@ -0,0 +1 @@ +DDDM \ No newline at end of file diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/16-c1-controls b/test/fuzz-libghostty/corpus/vt-stream-initial/16-c1-controls new file mode 100644 index 0000000000000000000000000000000000000000..aa8ead46eee68a146a87c5e536d4b93b151b8e29 GIT binary patch literal 15 WcmZRWZETo3*SAt3B(o$Zbq)Y183m32 literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/17-tab-backspace b/test/fuzz-libghostty/corpus/vt-stream-initial/17-tab-backspace new file mode 100644 index 0000000000000000000000000000000000000000..9ace2ee6df0e4c75c594a0db964674aedb4ee244 GIT binary patch literal 9 QcmZSJbmVm6bmrgy00f-?@&Et; literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/18-insert-delete b/test/fuzz-libghostty/corpus/vt-stream-initial/18-insert-delete new file mode 100644 index 000000000..3b6ad631b --- /dev/null +++ b/test/fuzz-libghostty/corpus/vt-stream-initial/18-insert-delete @@ -0,0 +1 @@ +[3@ \ No newline at end of file diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/19-many-params b/test/fuzz-libghostty/corpus/vt-stream-initial/19-many-params new file mode 100644 index 0000000000000000000000000000000000000000..756ad9d9a3467d860844417d0fd6e21166833749 GIT binary patch literal 42 xcmZROjyAM5vNpChu{O0fvo^Q3u(q@|G_W=_v^F%dHZ-<2G_f``wKg=%1pv9F2=V{` literal 0 HcmV?d00001 diff --git a/test/fuzz-libghostty/corpus/vt-stream-initial/20-csi-subparams b/test/fuzz-libghostty/corpus/vt-stream-initial/20-csi-subparams new file mode 100644 index 0000000000000000000000000000000000000000..571617bc37e7f2f179b0d479094ae44378919acf GIT binary patch literal 27 icmZROjyATiGO{u