| 1 |
# Seed corpora |
| 2 |
|
| 3 |
Hand-written and real starting inputs, one directory per fuzz target. These are |
| 4 |
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.** The `doc-` files are the protocol |
| 10 |
documentation's own examples. The `real-` files are genuine transmissions: a |
| 11 |
48x48 PNG off this machine sent both single-shot and in the 4096-character |
| 12 |
chunks a client actually uses, and raw RGB and RGBA frames whose dimensions |
| 13 |
agree with their payloads. Three are transmissions long enough to be chunked |
| 14 |
in earnest: a 64x64 RGBA frame in twenty-two 1024-character chunks, two |
| 15 |
chunked transmissions under different `i=` values sent back to back, and an |
| 16 |
animation that transmits a root frame, appends to it, composes and deletes. |
| 17 |
Chunk equivalence is the |
| 18 |
property with teeth in this oracle, and a corpus whose every payload fits in |
| 19 |
one body never reaches it. The rest is one file per shape worth reaching in |
| 20 |
the first second rather than the first hour: each medium a query can ask |
| 21 |
about, each way a chunked transfer is keyed, and the malformed bodies that |
| 22 |
sit one mutation away from a valid one. |
| 23 |
- **`corpus/` is machine output and lives on astra**, under the soak runner's |
| 24 |
persistent directory. Minimize with `cargo +nightly fuzz cmin apc` and commit |
| 25 |
it once it represents real soak hours, not before. |
| 26 |
|
| 27 |
## Input format |
| 28 |
|
| 29 |
The input is split on ESC and each piece has a leading `_` and a trailing `\` |
| 30 |
stripped, so a seed is what a client writes to the terminal, verbatim. A file |
| 31 |
holding several APCs is one session through one parser, which is how chunked |
| 32 |
transfers and the never-evicted partial state get reached at all. |
| 33 |
|
| 34 |
Run against these on a machine with no corpus: |
| 35 |
|
| 36 |
mkdir -p fuzz/corpus/apc |
| 37 |
cargo +nightly fuzz run apc fuzz/corpus/apc fuzz/seeds/apc |
| 38 |
|
| 39 |
The `mkdir` is needed once. `cargo fuzz` creates the default corpus directory |
| 40 |
for you only when you name no directories at all; pass them explicitly and |
| 41 |
libFuzzer requires every one to exist already. |
| 42 |
|
| 43 |
**Name the corpus directory first and this one second.** libFuzzer writes new |
| 44 |
inputs into whichever directory it is given first and treats the rest as |
| 45 |
read-only. Passing `fuzz/seeds/apc` alone dumps thousands of machine-generated |
| 46 |
files in here and buries the hand-written ones, which is exactly the split this |
| 47 |
directory exists to keep. |
| 48 |
|
| 49 |
## Where real payloads come from |
| 50 |
|
| 51 |
Not from `kitten icat`: headless it cannot open a controlling terminal, and |
| 52 |
under `script(1)` it refuses because the terminal reports no pixel size. There |
| 53 |
is no kitty graphics test corpus in the Debian package either. The two routes |
| 54 |
that work are building the payloads from a real image, which is what the |
| 55 |
`real-` seeds are, and recording a live client with `shop --record PATH`, which |
| 56 |
tees the PTY byte stream through `Pty::set_recorder`. |
| 57 |
|
| 58 |
## Crash seeds |
| 59 |
|
| 60 |
An input that once found a bug stays here forever, and also becomes a file |
| 61 |
under `fuzz/regressions/`, which `tests/regressions.rs` replays on stable. None |
| 62 |
yet. |
| 63 |
|