Skip to main content

max / shop

3.1 KB · 63 lines History Blame Raw
1 # Seed corpora
2
3 Hand-written and captured starting inputs, one directory per fuzz target.
4 These are committed; `corpus/` is not.
5
6 The split follows `astra-soak-overview`, which calls a minimized corpus
7 "accumulated compute, not a build artifact":
8
9 - **These seeds are human intent.** Most are real terminal traffic, captured
10 under `script(1)` from the twelve vtebench benchmarks and from eight
11 ordinary programs (`ls --color -R`, `top -b`, a coloured
12 `git log --graph`, helix, nano, btop, less, tmux), sliced at escape
13 boundaries. The rest is one file per protocol shape worth reaching in the
14 first second rather than the first hour: each string state, the scroll
15 region, the alt screen, wide characters at the right edge, truncated UTF-8,
16 and the queries a program waits on an answer for.
17 - **`corpus/` is machine output and lives on astra**, under the soak runner's
18 persistent directory. Minimize with `cargo +nightly fuzz cmin vt` and commit
19 it once it represents real soak hours, not before.
20
21 ## Input format
22
23 The first two bytes of every input choose the grid: `1 + b[0] % 200` columns
24 and `1 + b[1] % 60` rows. Everything after them is the byte stream. The
25 captured seeds carry a 100x30 header, so they are a capture with two bytes in
26 front rather than a different format. One seed picks a 1x1 grid, which is the
27 degenerate case every piece of the ring arithmetic has to survive.
28
29 Run against these on a machine with no corpus:
30
31 mkdir -p fuzz/corpus/vt
32 cargo +nightly fuzz run vt fuzz/corpus/vt fuzz/seeds/vt
33
34 The `mkdir` is needed once. `cargo fuzz` creates the default corpus directory
35 for you only when you name no directories at all; pass them explicitly and
36 libFuzzer requires every one to exist already.
37
38 **Name the corpus directory first and this one second.** libFuzzer writes new
39 inputs into whichever directory it is given first and treats the rest as
40 read-only. Passing `fuzz/seeds/vt` alone dumps thousands of machine-generated
41 files in here and buries the hand-written ones, which is exactly the split this
42 directory exists to keep.
43
44 ## Crash seeds
45
46 An input that once found a bug stays here forever, and also becomes a file
47 under `fuzz/regressions/`, which `tests/regressions.rs` replays on stable.
48
49 - `63-decstbm-inverted`. `ESC [ 20 ; 3 r` sets a scroll region whose top is
50 below its bottom, and `scroll_up_in_region` computes `bottom - top + 1`: an
51 underflow, so a panic in debug and a region of about 65,000 rows in release,
52 feeding a row index off the end of the ring into the unchecked store in
53 `place_char`.
54 - `104-delete-lines-whole-region`. `ESC [ 9999 M` on the top row of the
55 region. DL clamps its count to the region size, and a copy loop that computes
56 `scroll_bottom - n` underflows once the delete covers the whole region from
57 its first row.
58 - `106-pad-then-narrow-write`. A wide character with one column left leaves a
59 pad at the right edge. Reading that pad as the second half of a pair makes a
60 narrow write over it blank the cell two columns back, which is a real spacer,
61 leaving its lead on screen as half a character. No panic, so only the
62 wide-pair invariant catches it.
63