From 5e64012aaed196aeb5fff9d4c866dbc5ef85d18c Mon Sep 17 00:00:00 2001 From: Interchouette <484423+Interchouette@users.noreply.github.com> Date: Fri, 11 Sep 2026 21:12:51 +0200 Subject: [PATCH] chore(fuzz): add parse-html target, make fuzz and geiger Wire cargo-fuzz for rangular_parser::parse and cargo-geiger Make target. Local-only; CI stays unchanged. Co-authored-by: Cursor --- .gitignore | 4 + Cargo.toml | 2 +- Makefile | 20 ++++- docs/CONTRIBUTING.md | 2 + fuzz/Cargo.lock | 155 ++++++++++++++++++++++++++++++++ fuzz/Cargo.toml | 19 ++++ fuzz/fuzz_targets/parse_html.rs | 10 +++ 7 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 fuzz/Cargo.lock create mode 100644 fuzz/Cargo.toml create mode 100644 fuzz/fuzz_targets/parse_html.rs diff --git a/.gitignore b/.gitignore index e4541c0..572bd74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ /target/ coverage/ +fuzz/target/ +fuzz/corpus/ +fuzz/artifacts/ +fuzz/coverage/ /demo-leptos/dist/ /demo-leptos/target/ /demo-tauri/src/target/ diff --git a/Cargo.toml b/Cargo.toml index afd7732..56a746c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ "crates/rangular-parser", "crates/rangular-runtime", ] -exclude = ["demo-leptos", "demo-tauri/src"] +exclude = ["demo-leptos", "demo-tauri/src", "fuzz"] resolver = "3" [workspace.package] diff --git a/Makefile b/Makefile index 42c0423..6410f8f 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ TAG ?= dev .DEFAULT_GOAL := help .PHONY: help check test lint format format-check clean ci no-panic coverage \ - coverage-summary coverage-html tarpaulin machete outdated \ + coverage-summary coverage-html tarpaulin machete outdated fuzz fuzz-build geiger \ doc doc-open doc-clean \ demo demo-leptos demo-build demo-leptos-build demo-check demo-leptos-check \ demo-desktop demo-tauri demo-desktop-build demo-tauri-build \ @@ -48,6 +48,9 @@ help: @echo " make tarpaulin cargo tarpaulin → coverage/tarpaulin/ (local alternate)" @echo " make machete cargo machete (unused deps)" @echo " make outdated cargo outdated --workspace" + @echo " make fuzz cargo +nightly fuzz run $(FUZZ_TARGET) (FUZZ_TIME=$(FUZZ_TIME)s)" + @echo " make fuzz-build cargo +nightly fuzz build" + @echo " make geiger cargo geiger (unsafe dependency audit)" @echo " make audit cargo audit" @echo " make deny cargo deny check" @echo " make format cargo fmt" @@ -138,6 +141,21 @@ machete: outdated: cd $(ROOT) && $(CARGO) outdated --workspace +## Default fuzz target: rangular_parser::parse (Angular-subset HTML). +## Requires nightly + `cargo install cargo-fuzz`. Override: FUZZ_TARGET=… FUZZ_TIME=… +FUZZ_TARGET ?= parse-html +FUZZ_TIME ?= 10 + +fuzz-build: + cd $(ROOT) && cargo +nightly fuzz build + +fuzz: + cd $(ROOT) && cargo +nightly fuzz run $(FUZZ_TARGET) -- -max_total_time=$(FUZZ_TIME) + +## Unsafe Rust surface in deps + workspace. Requires `cargo install cargo-geiger`. +geiger: + cd $(ROOT) && $(CARGO) geiger --workspace + ci: lint test no-panic doc audit deny ## rustdoc → `docs/api-rust/` (GitHub Pages publish folder). diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index d79aa8f..4e2f9ca 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -59,6 +59,8 @@ Adjust the relative path to match your layout. - Prefer one concern per PR. - Run `make lint` and `make test` before push. +- Local fuzz / unsafe audit: `make fuzz` (default target `parse-html`, needs nightly + + `cargo fuzz`) and `make geiger` (needs `cargo geiger`). - Conventional commits: `feat(parser): …`, `fix(aot): …`, etc. - PR body follows [`pull_request_template.md`](pull_request_template.md) (**Summary** + **Test plan** only). diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock new file mode 100644 index 0000000..96f2bf5 --- /dev/null +++ b/fuzz/Cargo.lock @@ -0,0 +1,155 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "cc" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005ec2760ca554fae18df7a11195552ec576cd665632a881bc011d5bb2fd4d80" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "find-msvc-tools" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d" + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", +] + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom", + "libc", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rangular-expr" +version = "1.0.2" +dependencies = [ + "rangular-host", +] + +[[package]] +name = "rangular-fuzz" +version = "0.0.0" +dependencies = [ + "libfuzzer-sys", + "rangular-parser", +] + +[[package]] +name = "rangular-host" +version = "1.0.2" +dependencies = [ + "regex", +] + +[[package]] +name = "rangular-parser" +version = "1.0.2" +dependencies = [ + "rangular-expr", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml new file mode 100644 index 0000000..2672269 --- /dev/null +++ b/fuzz/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "rangular-fuzz" +version = "0.0.0" +publish = false +edition = "2024" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" +rangular-parser = { path = "../crates/rangular-parser" } + +[[bin]] +name = "parse-html" +path = "fuzz_targets/parse_html.rs" +test = false +doc = false +bench = false diff --git a/fuzz/fuzz_targets/parse_html.rs b/fuzz/fuzz_targets/parse_html.rs new file mode 100644 index 0000000..9a88c4e --- /dev/null +++ b/fuzz/fuzz_targets/parse_html.rs @@ -0,0 +1,10 @@ +#![no_main] + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + let Ok(src) = std::str::from_utf8(data) else { + return; + }; + let _ = rangular_parser::parse(src, "fuzz.html"); +});