From ec6b997e949fa3e0ea67207434b760e9f2d58805 Mon Sep 17 00:00:00 2001 From: Greg von Nessi Date: Mon, 16 Feb 2026 16:00:11 +0000 Subject: [PATCH] Add fuzz targets for custom Block, Mark, and Content serde The hand-written Serialize/Deserialize impls from PR #87 are the most complex recent addition. These fuzz targets exercise all type dispatch paths with arbitrary input to catch panics or unexpected behavior in the custom deserialization logic. --- fuzz/Cargo.toml | 21 +++++++++++++++++++++ fuzz/fuzz_targets/block_parser.rs | 17 +++++++++++++++++ fuzz/fuzz_targets/content_parser.rs | 15 +++++++++++++++ fuzz/fuzz_targets/mark_parser.rs | 18 ++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 fuzz/fuzz_targets/block_parser.rs create mode 100644 fuzz/fuzz_targets/content_parser.rs create mode 100644 fuzz/fuzz_targets/mark_parser.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 0872306..cdde62e 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -36,3 +36,24 @@ path = "fuzz_targets/manifest_parser.rs" test = false doc = false bench = false + +[[bin]] +name = "block_parser" +path = "fuzz_targets/block_parser.rs" +test = false +doc = false +bench = false + +[[bin]] +name = "mark_parser" +path = "fuzz_targets/mark_parser.rs" +test = false +doc = false +bench = false + +[[bin]] +name = "content_parser" +path = "fuzz_targets/content_parser.rs" +test = false +doc = false +bench = false diff --git a/fuzz/fuzz_targets/block_parser.rs b/fuzz/fuzz_targets/block_parser.rs new file mode 100644 index 0000000..d261982 --- /dev/null +++ b/fuzz/fuzz_targets/block_parser.rs @@ -0,0 +1,17 @@ +//! Fuzz target for Block deserialization. +//! +//! This target tests the custom `Deserialize` impl for `Block` which +//! dispatches on the `"type"` field to construct the correct variant. +//! Exercises all 20+ block type code paths with arbitrary JSON input. + +#![no_main] + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + // Try parsing as a single Block + let _ = serde_json::from_slice::(data); + + // Also try parsing as a Vec (nested children) + let _ = serde_json::from_slice::>(data); +}); diff --git a/fuzz/fuzz_targets/content_parser.rs b/fuzz/fuzz_targets/content_parser.rs new file mode 100644 index 0000000..b2897fb --- /dev/null +++ b/fuzz/fuzz_targets/content_parser.rs @@ -0,0 +1,15 @@ +//! Fuzz target for Content deserialization. +//! +//! This target tests parsing of the full `Content` structure which +//! contains a version field and a blocks array. Exercises the complete +//! content deserialization pipeline including nested blocks and text +//! nodes with marks. + +#![no_main] + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + // Try parsing as a full Content structure + let _ = serde_json::from_slice::(data); +}); diff --git a/fuzz/fuzz_targets/mark_parser.rs b/fuzz/fuzz_targets/mark_parser.rs new file mode 100644 index 0000000..2b17192 --- /dev/null +++ b/fuzz/fuzz_targets/mark_parser.rs @@ -0,0 +1,18 @@ +//! Fuzz target for Mark deserialization. +//! +//! This target tests the custom `Deserialize` impl for `Mark` which +//! handles both simple string marks (e.g., `"bold"`) and complex object +//! marks (e.g., `{"type": "link", "href": "..."}`). Exercises all 15+ +//! mark type code paths with arbitrary input. + +#![no_main] + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + // Try parsing as a single Mark + let _ = serde_json::from_slice::(data); + + // Also try parsing as a Vec (text node marks array) + let _ = serde_json::from_slice::>(data); +});