mirror of
https://github.com/askama-rs/askama.git
synced 2025-09-28 05:21:14 +00:00
fuzz: fuzz everything at once
This commit is contained in:
parent
79873f6a17
commit
1176c654ba
@ -6,8 +6,9 @@ license = "MIT OR Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
fuzz = { path = "fuzz"}
|
||||
fuzz = { path = "fuzz" }
|
||||
|
||||
arbitrary = "1.3.2"
|
||||
pretty-error-debug = "0.3.0"
|
||||
thiserror = "1.0.63"
|
||||
|
||||
|
@ -13,7 +13,7 @@ Then execute in this folder:
|
||||
RUST_BACKTRACE=1 nice cargo +nightly fuzz run <fuzz_target>
|
||||
```
|
||||
|
||||
`fuzz_target` is one out of `html` or `parser`.
|
||||
`fuzz_target` is one out of `all`, `html` or `parser`.
|
||||
|
||||
The execution won't stop, but continue until you kill it with ctrl+c.
|
||||
Or until it finds a panic.
|
||||
|
@ -15,6 +15,12 @@ arbitrary = { version = "1.3.2", features = ["derive"] }
|
||||
html-escape = "0.2.13"
|
||||
libfuzzer-sys = "0.4.7"
|
||||
|
||||
[[bin]]
|
||||
name = "all"
|
||||
path = "fuzz_targets/all.rs"
|
||||
test = false
|
||||
doc = false
|
||||
|
||||
[[bin]]
|
||||
name = "html"
|
||||
path = "fuzz_targets/html.rs"
|
||||
|
9
fuzzing/fuzz/fuzz_targets/all.rs
Normal file
9
fuzzing/fuzz/fuzz_targets/all.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![no_main]
|
||||
|
||||
use fuzz::Scenario;
|
||||
|
||||
libfuzzer_sys::fuzz_target!(|data: &[u8]| {
|
||||
if let Ok(scenario) = fuzz::all::Scenario::new(data) {
|
||||
let _ = scenario.run();
|
||||
}
|
||||
});
|
70
fuzzing/fuzz/src/all.rs
Normal file
70
fuzzing/fuzz/src/all.rs
Normal file
@ -0,0 +1,70 @@
|
||||
macro_rules! this_file {
|
||||
($(crate :: $mod:ident :: $ty:ident;)*) => {
|
||||
use std::fmt;
|
||||
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Scenario<'a> {
|
||||
$($ty(crate::$mod::Scenario<'a>),)*
|
||||
}
|
||||
|
||||
impl<'a> super::Scenario<'a> for Scenario<'a> {
|
||||
type RunError = RunError;
|
||||
|
||||
fn new(data: &'a [u8]) -> Result<Self, arbitrary::Error> {
|
||||
let mut data = Unstructured::new(data);
|
||||
let target = Arbitrary::arbitrary(&mut data)?;
|
||||
let data = Arbitrary::arbitrary_take_rest(data)?;
|
||||
|
||||
match target {
|
||||
$(Target::$ty => Ok(Self::$ty(crate::$mod::Scenario::new(data)?)),)*
|
||||
}
|
||||
}
|
||||
|
||||
fn run(&self) -> Result<(), Self::RunError> {
|
||||
match self {
|
||||
$(Self::$ty(scenario) => scenario.run().map_err(RunError::$ty),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Arbitrary)]
|
||||
enum Target {
|
||||
$($ty,)*
|
||||
}
|
||||
|
||||
pub enum RunError {
|
||||
$($ty(<crate::$mod::Scenario<'static> as crate::Scenario<'static>>::RunError),)*
|
||||
}
|
||||
|
||||
impl fmt::Display for RunError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
$(Self::$ty(err) => err.fmt(f),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for RunError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
$(Self::$ty(err) => err.fmt(f),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for RunError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
$(RunError::$ty(err) => Some(err),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this_file! {
|
||||
crate::html::Html;
|
||||
crate::parser::Parser;
|
||||
}
|
@ -11,11 +11,9 @@ pub enum Scenario<'a> {
|
||||
}
|
||||
|
||||
impl<'a> super::Scenario<'a> for Scenario<'a> {
|
||||
type NewError = arbitrary::Error;
|
||||
|
||||
type RunError = std::convert::Infallible;
|
||||
|
||||
fn new(data: &'a [u8]) -> Result<Self, Self::NewError> {
|
||||
fn new(data: &'a [u8]) -> Result<Self, arbitrary::Error> {
|
||||
Self::arbitrary_take_rest(Unstructured::new(data))
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod all;
|
||||
pub mod html;
|
||||
pub mod parser;
|
||||
|
||||
@ -5,18 +6,17 @@ use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
pub const TARGETS: &[(&str, TargetBuilder)] = &[
|
||||
("all", |data| NamedTarget::new::<all::Scenario>(data)),
|
||||
("html", |data| NamedTarget::new::<html::Scenario>(data)),
|
||||
("parser", |data| NamedTarget::new::<parser::Scenario>(data)),
|
||||
];
|
||||
|
||||
pub type TargetBuilder =
|
||||
for<'a> fn(&'a [u8]) -> Result<NamedTarget<'a>, Box<dyn Error + Send + 'static>>;
|
||||
pub type TargetBuilder = for<'a> fn(&'a [u8]) -> Result<NamedTarget<'a>, arbitrary::Error>;
|
||||
|
||||
pub trait Scenario<'a>: fmt::Debug + Sized {
|
||||
type NewError: Error + Send + 'static;
|
||||
type RunError: Error + Send + 'static;
|
||||
|
||||
fn new(data: &'a [u8]) -> Result<Self, Self::NewError>;
|
||||
fn new(data: &'a [u8]) -> Result<Self, arbitrary::Error>;
|
||||
fn run(&self) -> Result<(), Self::RunError>;
|
||||
}
|
||||
|
||||
@ -53,11 +53,8 @@ impl fmt::Debug for NamedTarget<'_> {
|
||||
|
||||
impl<'a> NamedTarget<'a> {
|
||||
#[inline]
|
||||
fn new<S: Scenario<'a> + 'a>(data: &'a [u8]) -> Result<Self, Box<dyn Error + Send + 'static>> {
|
||||
match S::new(data) {
|
||||
Ok(scenario) => Ok(Self(Box::new(scenario))),
|
||||
Err(err) => Err(Box::new(err)),
|
||||
}
|
||||
fn new<S: Scenario<'a> + 'a>(data: &'a [u8]) -> Result<Self, arbitrary::Error> {
|
||||
Ok(Self(Box::new(S::new(data)?)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,9 @@ pub struct Scenario<'a> {
|
||||
}
|
||||
|
||||
impl<'a> super::Scenario<'a> for Scenario<'a> {
|
||||
type NewError = arbitrary::Error;
|
||||
|
||||
type RunError = rinja_parser::ParseError;
|
||||
|
||||
fn new(data: &'a [u8]) -> Result<Self, Self::NewError> {
|
||||
fn new(data: &'a [u8]) -> Result<Self, arbitrary::Error> {
|
||||
let mut data = Unstructured::new(data);
|
||||
|
||||
let syntax = ArbitrarySyntax::arbitrary(&mut data)?;
|
||||
|
@ -52,7 +52,7 @@ enum Error {
|
||||
#[error("could not read opened input file {}", .1.display())]
|
||||
Read(#[source] std::io::Error, PathBuf),
|
||||
#[error("could not build scenario")]
|
||||
Build(#[source] Box<dyn std::error::Error + Send + 'static>),
|
||||
Build(#[source] arbitrary::Error),
|
||||
#[error("could not run scenario")]
|
||||
Run(#[source] Box<dyn std::error::Error + Send + 'static>),
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user