max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+26 insertions,
-1 deletion
| @@ -52,6 +52,31 @@ | |||
| 52 | 52 | .expect("the fixture policy is well-formed") | |
| 53 | 53 | }); | |
| 54 | 54 | ||
| 55 | + | /// The oracle runs on its own thread, with a large stack. | |
| 56 | + | /// | |
| 57 | + | /// Not a workaround for a defect in the crate: the SANITIZER is fine on a 2 MB | |
| 58 | + | /// stack, which is what tokio gives a worker, and that was measured against the | |
| 59 | + | /// input that prompted this (243 bytes in, 381 KB of flattened CSS out, survives | |
| 60 | + | /// at 2 MB). What needs the room is the ORACLE's own reparse of that output, | |
| 61 | + | /// which recurses per nesting level in a build where AddressSanitizer makes | |
| 62 | + | /// every frame several times its normal size. | |
| 63 | + | /// | |
| 64 | + | /// The alternative was to stop checking large outputs, which would have blinded | |
| 65 | + | /// the target on exactly the inputs most worth checking -- the ones that | |
| 66 | + | /// amplify. Stack is cheaper than coverage. | |
| 67 | + | fn checked(input: &str) { | |
| 68 | + | let owned = input.to_string(); | |
| 69 | + | let handle = std::thread::Builder::new() | |
| 70 | + | .stack_size(256 * 1024 * 1024) | |
| 71 | + | .spawn(move || custom_pages::oracle::check_css(&owned, OWNER_SCOPE, &POLICY)) | |
| 72 | + | .expect("spawning the oracle thread"); | |
| 73 | + | // Propagate a panic rather than swallowing it: the panic IS the finding, and | |
| 74 | + | // a target that joined and ignored the result would report clean forever. | |
| 75 | + | if let Err(payload) = handle.join() { | |
| 76 | + | std::panic::resume_unwind(payload); | |
| 77 | + | } | |
| 78 | + | } | |
| 79 | + | ||
| 55 | 80 | fuzz_target!(|input: &str| { | |
| 56 | - | custom_pages::oracle::check_css(input, OWNER_SCOPE, &POLICY); | |
| 81 | + | checked(input); | |
| 57 | 82 | }); |