Never crash: the fuzz job's eleven hangs finish (parser retries, inline images, Type 3 fan-out)

Every hang the nightly fuzz job found (11 findings, 8 source files) now
finishes in 0.1-2 s; each cause has a synthetic regression test that times
out without its fix.
- cos (7 findings, our own parser): a stream whose /Length pointed at
  itself, with no endstream, made every parse attempt fail and each attempt
  reload the same object: ~2^32 parses. Objects being loaded are a seen-set,
  /Length values are memoised per load, and the shifted-header retry only
  runs when the header is shifted.
- hayro-syntax (3): deciding where an inline image's data ends re-parsed the
  rest of the stream, nesting through every inline image; 50 images ran for
  over ten minutes. The look-ahead no longer nests and is bounded (256).
- hayro-interpret (1): a Type 3 glyph showing eight glyphs of its own font,
  sixteen deep. Nested paints share a per-page budget (50,000).
The pdf.js corpus sweep matches its baseline (963 ok, same 20 known).
xtask check writes its report under CARGO_TARGET_DIR too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-05 07:35:38 -04:00
co-authored by Claude Opus 5.5
parent f97684f0d8
commit 2f364665b8
8 changed files with 182 additions and 30 deletions
+9 -5
View File
@@ -12,11 +12,15 @@ pub fn root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).parent().expect("xtask has a parent dir").to_path_buf()
}
/// The release `printcraft-cli` that `cargo build --release -p printcraft-cli` produced: under
/// `CARGO_TARGET_DIR` when it is set (parallel agents use their own), else `target/`.
/// Cargo's target directory: `CARGO_TARGET_DIR` when it is set (parallel agents use their own),
/// else `target/`.
pub fn target_dir() -> PathBuf {
std::env::var_os("CARGO_TARGET_DIR").map_or_else(|| root().join("target"), |d| root().join(d))
}
/// The release `printcraft-cli` that `cargo build --release -p printcraft-cli` produced.
pub fn release_cli() -> PathBuf {
let target = std::env::var_os("CARGO_TARGET_DIR").map_or_else(|| root().join("target"), |d| root().join(d));
target.join("release").join(format!("printcraft-cli{}", std::env::consts::EXE_SUFFIX))
target_dir().join("release").join(format!("printcraft-cli{}", std::env::consts::EXE_SUFFIX))
}
fn cargo() -> Command {
@@ -163,7 +167,7 @@ pub fn check(args: &[String]) -> anyhow::Result<()> {
bail!("corpus missing: run `cargo xtask corpus` first");
}
run_args(&["build", "--release", "-p", "printcraft-cli"])?;
let report = root().join("target/check-pdfjs.json");
let report = target_dir().join("check-pdfjs.json");
let mut c = Command::new(release_cli());
c.args(["check"]).arg(&corpus).args(["--timeout", "20", "--dpi", "36", "--json"]).arg(&report);
run(c, "printcraft-cli check corpus/pdfjs")?;