Skip to main content

max / makenotwork

2.3 KB · 50 lines History Blame Raw
1 //! Structured fuzz over multipart part geometry.
2 //!
3 //! Row 7 of `astra-soak-overview` (upload + object path), and the fourth
4 //! target built there. The doors were counted before this was
5 //! written, as infra `8910f917` instructs, and the count decided the shape:
6 //! almost all of `s3-storage` is async I/O against a live endpoint and is not
7 //! fuzzable without one, while `MultipartPlan` is pure arithmetic with four
8 //! call sites in MNW server and one implementation behind them.
9 //!
10 //! `MultipartPlan`'s docs say the client computes the same boundaries
11 //! independently, which reads like the two-parsers shape that made a shared
12 //! crate the answer for `git_ssh`. It is not: SyncKit's check is a one-line
13 //! restatement (`size_bytes.div_ceil(part_size) == part_count`), so a
14 //! differential would measure nothing the property does not. The property is
15 //! asserted instead, and it is the first thing `oracle::check_plan` checks.
16 //!
17 //! ## Why this path is worth a target
18 //!
19 //! It is what creator media travels through, and it fails in two directions.
20 //! Parts that do not tile the object exactly mean corrupted or truncated media,
21 //! invisible until playback. A plan refused when it should not be means a
22 //! legitimate upload rejected. The oracle asserts both, which is why it checks
23 //! the error paths as tightly as the success path.
24
25 #![no_main]
26
27 use libfuzzer_sys::fuzz_target;
28
29 /// S3's own bounds, restated so the shaped call below always lands inside them.
30 const MIN_PART: u64 = 5 * 1024 * 1024;
31 const MAX_PART: u64 = 5 * 1024 * 1024 * 1024;
32
33 fuzz_target!(|input: (u64, u64)| {
34 let (total_size, raw_part) = input;
35
36 // The raw pair, which is mostly refusals. Worth running: "every rejection
37 // names a condition that actually holds" is half of what the oracle
38 // asserts, and it is the half that protects legitimate uploads.
39 s3_storage::oracle::check_plan(total_size, raw_part as usize);
40
41 // A part size guaranteed inside S3's window, so the success path is
42 // exercised on every input rather than only when random bytes happen to
43 // land in a range that is a vanishing fraction of u64.
44 let shaped = MIN_PART + (raw_part % (MAX_PART - MIN_PART + 1));
45 s3_storage::oracle::check_plan(total_size, shaped as usize);
46
47 // The entry point the four real call sites actually use.
48 s3_storage::oracle::check_auto(total_size);
49 });
50