From ad4cf1c0dedbcd3893357eded7255745456863e9 Mon Sep 17 00:00:00 2001 From: Colin Rofls Date: Wed, 21 Aug 2024 18:18:00 -0400 Subject: [PATCH] Test out simple generic fuzzing using traversal --- fuzz/Cargo.toml | 18 ++++++++++++++++++ fuzz/fuzz_targets/fuzz_gdef.rs | 7 +++++++ fuzz/fuzz_targets/fuzz_gpos.rs | 7 +++++++ fuzz/fuzz_targets/fuzz_gsub.rs | 7 +++++++ fuzz/fuzz_targets/traversal_fuzz.rs | 28 ++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 fuzz/fuzz_targets/fuzz_gdef.rs create mode 100644 fuzz/fuzz_targets/fuzz_gpos.rs create mode 100644 fuzz/fuzz_targets/fuzz_gsub.rs create mode 100644 fuzz/fuzz_targets/traversal_fuzz.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 299488f65..0ab725261 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -67,3 +67,21 @@ name = "fuzz_sparse_bit_set_encode" path = "fuzz_targets/fuzz_sparse_bit_set_encode.rs" test = false doc = false + +[[bin]] +name = "fuzz_gdef" +path = "fuzz_targets/fuzz_gdef.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_gpos" +path = "fuzz_targets/fuzz_gpos.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_gsub" +path = "fuzz_targets/fuzz_gsub.rs" +test = false +doc = false diff --git a/fuzz/fuzz_targets/fuzz_gdef.rs b/fuzz/fuzz_targets/fuzz_gdef.rs new file mode 100644 index 000000000..45f141970 --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_gdef.rs @@ -0,0 +1,7 @@ +#![no_main] + +mod traversal_fuzz; +use libfuzzer_sys::{fuzz_target, Corpus}; +use read_fonts::tables::gdef::Gdef; + +fuzz_target!(|data: &[u8]| -> Corpus { traversal_fuzz::try_traverse_table::(data, false) }); diff --git a/fuzz/fuzz_targets/fuzz_gpos.rs b/fuzz/fuzz_targets/fuzz_gpos.rs new file mode 100644 index 000000000..cfe62138e --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_gpos.rs @@ -0,0 +1,7 @@ +#![no_main] + +mod traversal_fuzz; +use libfuzzer_sys::{fuzz_target, Corpus}; +use read_fonts::tables::gpos::Gpos; + +fuzz_target!(|data: &[u8]| -> Corpus { traversal_fuzz::try_traverse_table::(data, false) }); diff --git a/fuzz/fuzz_targets/fuzz_gsub.rs b/fuzz/fuzz_targets/fuzz_gsub.rs new file mode 100644 index 000000000..25b6096df --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_gsub.rs @@ -0,0 +1,7 @@ +#![no_main] + +mod traversal_fuzz; +use libfuzzer_sys::{fuzz_target, Corpus}; +use read_fonts::tables::gsub::Gsub; + +fuzz_target!(|data: &[u8]| -> Corpus { traversal_fuzz::try_traverse_table::(data, false) }); diff --git a/fuzz/fuzz_targets/traversal_fuzz.rs b/fuzz/fuzz_targets/traversal_fuzz.rs new file mode 100644 index 000000000..01505e479 --- /dev/null +++ b/fuzz/fuzz_targets/traversal_fuzz.rs @@ -0,0 +1,28 @@ +use std::fmt::Debug; +use std::io::Write; + +use libfuzzer_sys::Corpus; +use read_fonts::FontRead; + +/// Reusable entry point to fuzz any table via traversal +/// +/// To debug timeouts, set `print_output` to `true` (the output text will help +/// show where you're hitting a loop) +pub fn try_traverse_table<'a, T: FontRead<'a> + Debug>( + data: &'a [u8], + print_output: bool, +) -> Corpus { + match T::read(data.into()) { + Err(_) => Corpus::Reject, + Ok(table) => { + if print_output { + let _ = writeln!(std::io::stderr(), "{table:?}"); + } else { + // if we don't want to see the output don't bother filling a buffer + let mut empty = std::io::empty(); + write!(&mut empty, "{table:?}").unwrap(); + } + Corpus::Keep + } + } +}