diff --git a/crates/js/fuzz/Cargo.toml b/crates/js/fuzz/Cargo.toml new file mode 100644 index 0000000000..373028192e --- /dev/null +++ b/crates/js/fuzz/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "pdfcraft-js-fuzz" +version = "0.0.0" +publish = false +edition = "2024" +license = "MIT OR Apache-2.0" + +[package.metadata] +cargo-fuzz = true + +# Detached from the PdfCraft workspace: run with `cargo +nightly fuzz run run_script` +# from crates/js/. +[workspace] + +[dependencies] +libfuzzer-sys = "0.4" +pdfcraft-js = { path = ".." } + +[[bin]] +name = "run_script" +path = "fuzz_targets/run_script.rs" +test = false +doc = false +bench = false diff --git a/crates/js/fuzz/fuzz_targets/run_script.rs b/crates/js/fuzz/fuzz_targets/run_script.rs new file mode 100644 index 0000000000..57ccb9ea66 --- /dev/null +++ b/crates/js/fuzz/fuzz_targets/run_script.rs @@ -0,0 +1,26 @@ +//! Feeds arbitrary bytes, read as a script, to the JavaScript run entry with fixed event and document values. +//! +//! The run's result is discarded: the target only checks that no input panics or hangs past the limits. +#![no_main] + +use libfuzzer_sys::fuzz_target; +use pdfcraft_js::{DocInfo, Event, Limits, run}; + +/// The largest script the target runs (64 KiB); larger inputs are skipped. +const MAX_INPUT: usize = 64 << 10; + +fuzz_target!(|data: &[u8]| { + if data.len() > MAX_INPUT { + return; + } + let script = String::from_utf8_lossy(data).into_owned(); + let event = Event { + name: "Keystroke".into(), + kind: "Field".into(), + target: Some("field1".into()), + value: "value".into(), + change: String::new(), + will_commit: true, + }; + let _outcome = run(&script, &event, &DocInfo::default(), &[], &[], Limits::default()); +});