/src/pulldown-cmark/fuzz/fuzz_targets/commonmark_js.rs
Line | Count | Source |
1 | | #![no_main] |
2 | | |
3 | | //! Differential fuzzing of pulldown-cmark and commonmark.js. |
4 | | //! |
5 | | //! This fuzzer sends the same input to both Markdown parsers and |
6 | | //! compares the output. The output from commonmark.js is turned into |
7 | | //! `pulldown_cmark::Event` values for this purpose. |
8 | | //! |
9 | | //! Run the fuzzer like this to only test ASCII input (which is |
10 | | //! usually enough to find parsing differences): |
11 | | //! |
12 | | //! cargo fuzz run commonmark_js -- -only_ascii=1 |
13 | | |
14 | | use libfuzzer_sys::fuzz_target; |
15 | | use pretty_assertions::assert_eq; |
16 | | use pulldown_cmark_fuzz::{commonmark_js, normalize, print_events, pulldown_cmark, xml_to_events}; |
17 | | |
18 | | fuzz_target!(|text: String| { |
19 | | // There are some differences in handling of non-UTF-8 input. |
20 | 224M | if text.bytes().any(|b| b.is_ascii_control() && b != b'\n') { |
21 | | return; |
22 | | } |
23 | | |
24 | | // There are some trivial differences due to trailing whitespace. |
25 | | let text = text |
26 | | .lines() |
27 | 13.1M | .map(|line| line.trim_end()) |
28 | | .collect::<Vec<_>>() |
29 | | .join("\n"); |
30 | | |
31 | | let pulldown_cmark_events = normalize(pulldown_cmark(&text)); |
32 | | let commonmark_js_xml = &commonmark_js(&text).unwrap(); |
33 | | |
34 | | let raw_events = match xml_to_events(commonmark_js_xml) { |
35 | | Ok(raw_events) => raw_events, |
36 | | Err(err) => { |
37 | | print_events(&text, &pulldown_cmark_events); |
38 | | eprintln!("XML from commonmark.js:\n{commonmark_js_xml}"); |
39 | | panic!("Could not parse XML: {}", err); |
40 | | } |
41 | | }; |
42 | | |
43 | | let commonmark_js_events = normalize(raw_events); |
44 | | if pulldown_cmark_events != commonmark_js_events { |
45 | | eprintln!("Events from pulldown-cmark:\n\n```rust"); |
46 | | print_events(&text, &pulldown_cmark_events); |
47 | | eprintln!("```"); |
48 | | eprintln!(); |
49 | | |
50 | | eprintln!("Events from commonmark.js:\n\n```rust"); |
51 | | print_events(&text, &commonmark_js_events); |
52 | | eprintln!("```"); |
53 | | eprintln!(); |
54 | | |
55 | | let dingus_url = format!( |
56 | | "https://spec.commonmark.org/dingus/?text={}", |
57 | | urlencoding::encode(&text) |
58 | | ); |
59 | | eprintln!("XML from [commonmark.js]({dingus_url}):\n\n```xml\n{commonmark_js_xml}```"); |
60 | | eprintln!(); |
61 | | |
62 | | assert_eq!(pulldown_cmark_events, commonmark_js_events); |
63 | | } |
64 | | }); |