public sealed class FuzzSessionRuns one target until it is told to stop, and holds it to its promises.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
The oracles are the point, not the loop. Pushing bytes at a decoder proves nothing on its own — the decoder has to be measured while it does it. Four things are measured: that nothing was thrown, that the allocation was proportionate to the input, that nothing was retained, and that the case finished quickly. Everything else about the decode is the target's business — including, since Domain, how its inputs were made. None of the four asks what an input is, which is what let that be added without disturbing any of them.
⚠ All four are computed after Run returns, and that is a hole rather than a detail. An input that makes a decoder loop, or grow the heap without bound, never lets it return — so the readings that would have caught it are never taken and the run is ended by the operating system killing the machine instead. A fifth, RanAway, is watched for during the call by CaseGuard, on another thread, so that such an input is a named finding with its bytes on disk rather than a dead host and a guess. Read that type for what the guard cannot do, which is take the thread back.
Deterministic, and that is a requirement rather than a nicety. The generator is seeded, the mutations are a pure function of it, and the corpus grows in a fixed order, so a failure on a CI machine is reproduced locally from the seed and the target name. A fuzzer whose findings cannot be replayed has handed you a rumour.
It does not stop at the first finding. One malformed shape usually reaches several decoders and several of a decoder's paths, and a run that stops at the first one turns a morning's fixing into a week of one-a-day. It stops at MaxFindings, which is there so a target that throws on everything does not fill memory with the evidence.
⚠ That cap ends the run, and not only the collecting — reaffirmed rather than assumed, because it is what hid a compiler bug for weeks. The argument for bounding stored evidence does not by itself argue for stopping, and while the dedup key was the whole detail string it very nearly was not: one defect minted a fresh finding per byte offset, thirty-two of them filled the cap in five and a half minutes, and raven never once spent more than that of its two-hour nightly. The cap stays a stopping condition now that a finding means a distinct defect again, for a reason the old arithmetic did not have: past thirty-two of those there is nothing left to learn, and going on makes the search worse rather than longer — every failing input is offered to the corpus, so the mutator settles into the broken region and stops reaching anything else. What was actually missing was not more running but the ability to see that it had stopped, which is Stopped.
Fields and properties (10)
public const int MaxFindingsHow many findings are collected before a run gives up.
public const int WindowCasesHow many cases the allocation budget is measured over. See Weigh.
public TimeSpan CaseBudgetHow long one input may take to decode before that is itself the finding.
public TimeSpan HardCaseCapHow long one case may run before the run is abandoned rather than measured.
public long RunawayAllocationHow many bytes one case may be handed, garbage included, before it is abandoned.
public long RunawayRetentionHow far the heap may grow during one case before it is abandoned.
public bool AbandonProcessOnRunawayWhether a case that will not stop growing ends the process. See the guard.
public string? FindingDirectoryWhere a runaway's input is written the moment it is seen, or null not to.
public int WarmUpCasesHow many cases run before allocation is held against the target, so that one-off start-up costs are not reported as an amplifying packet.
public string? RegressionDirectoryWhere committed regression inputs are read from, or null to skip them.
Methods (3)
public FuzzSession(IFuzzTarget target, ulong seed)Creates a run over one target.
public FuzzOutcome Run(long cases)Runs a fixed number of cases.
public FuzzOutcome RunFor(TimeSpan budget)Runs for a length of time.
Used by (3)
- CaseGuardTestsVixen.Fuzz.Tests
- FindingDedupTestsVixen.Fuzz.Tests
- FuzzGateTestsVixen.Fuzz.Tests