diff --git a/meta/fuzz/Cargo.toml b/meta/fuzz/Cargo.toml index b2f074f9..7abfb152 100644 --- a/meta/fuzz/Cargo.toml +++ b/meta/fuzz/Cargo.toml @@ -8,6 +8,8 @@ rust-version = "1.56" [package.metadata] cargo-fuzz = true +[dependencies.pest] +path = "../../pest" [dependencies.pest_meta] path = ".." [dependencies.libfuzzer-sys] diff --git a/meta/fuzz/fuzz_targets/parser.rs b/meta/fuzz/fuzz_targets/parser.rs index 1e246c24..f9b8cad6 100644 --- a/meta/fuzz/fuzz_targets/parser.rs +++ b/meta/fuzz/fuzz_targets/parser.rs @@ -2,9 +2,13 @@ #[macro_use] extern crate libfuzzer_sys; extern crate pest_meta; +extern crate pest; + +use std::convert::TryInto; fuzz_target!(|data: &[u8]| { if let Ok(s) = std::str::from_utf8(data) { + pest::set_call_limit(Some(25_000usize.try_into().unwrap())); let _ = pest_meta::parser::parse(pest_meta::parser::Rule::grammar_rules, s); } }); diff --git a/meta/resources/test/fuzzsample1.grammar b/meta/resources/test/fuzzsample1.grammar new file mode 100644 index 00000000..c7adbcf0 --- /dev/null +++ b/meta/resources/test/fuzzsample1.grammar @@ -0,0 +1,245 @@ +w={ +(((((((((((((((((((((((((((((((( ((((((((((((((((((((( +((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( (((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( (((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( (((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( (((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( (((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( +((((( +((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( ((((((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((( +((((((((((((((((((((((((((((((//( (((((((((((((((((((((((((w={ +(( ((((((((((((((((((((((((((((( +((((( +((((((((((((((((((((((( ((((((((((((((((((((((((((((( +((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((( +((( (((((((((((((((((((((((( +((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( (((((((((((((((((((((((((((((( +((((((((((((((((((((((((((((((//( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((( (((((((((((((((((( ((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((( \ No newline at end of file diff --git a/meta/resources/test/fuzzsample2.grammar b/meta/resources/test/fuzzsample2.grammar new file mode 100644 index 00000000..f2f9f69b --- /dev/null +++ b/meta/resources/test/fuzzsample2.grammar @@ -0,0 +1,6 @@ + +/*//j/*/*;'//*//*/*/*;'/*//*/*;**//*//*/*/*;'/*/ /*//*/*/*;+/*//*/*;*B/*//*/*/*/*;'/*//*/*;**//*//*/*/*;'/*/ /*//*/*/*;+/*//*/*;*B/*//*//*/*;**N//*//*/*/*;'/*//*//*/ + +*//*/*;**N//*//*/*/*;'/*//*//*/ + +*/*;+/*//**/*/*;'/*//*//*;*/*///*/*; \ No newline at end of file diff --git a/meta/resources/test/fuzzsample3.grammar b/meta/resources/test/fuzzsample3.grammar new file mode 100644 index 00000000..02efa226 --- /dev/null +++ b/meta/resources/test/fuzzsample3.grammar @@ -0,0 +1,102 @@ +A=@{((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((PUSH(((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((PUSH((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((PUSH(((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( (((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( (((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((PUSH(((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((PUSH((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( (((((((((((((((((((((((((((((((((((((PUSH(((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( (((((((((((((( (((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( (((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( ((((((((((((((((((((( ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((! +(((((((((((((((((((((((((((((((((((((((((((((((((OOnOYYzOPUSH~OzOO)~OOOOz{1}{, + +3}{, + +1}{, + + +4}{ + +22, +6}{ + +22, + +2}{2, + + +3}{ + +2}{,4}{ +4}{ +22, + + +64444}{ +22, + + +6}{ + +0, +6}{ + +22, + +2}{2, + + +3}{ + +2}{,4}{ +23, + +(((((((((((((((((((((((((((((( + + + +? ((((((((( + + + + +f={"7MMg|g|&Hd_M \ No newline at end of file diff --git a/meta/src/parser.rs b/meta/src/parser.rs index 6526ef12..a5b2a078 100644 --- a/meta/src/parser.rs +++ b/meta/src/parser.rs @@ -621,6 +621,8 @@ fn unescape(string: &str) -> Option { #[cfg(test)] mod tests { + use std::convert::TryInto; + use super::super::unwrap_or_report; use super::*; @@ -1501,4 +1503,31 @@ mod tests { assert_eq!(unescape(string), None); } + + #[test] + fn handles_deep_nesting() { + let sample1 = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/resources/test/fuzzsample1.grammar" + )); + let sample2 = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/resources/test/fuzzsample2.grammar" + )); + let sample3 = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/resources/test/fuzzsample3.grammar" + )); + const ERROR: &str = "call limit reached"; + pest::set_call_limit(Some(25_000usize.try_into().unwrap())); + let s1 = crate::parser::parse(crate::parser::Rule::grammar_rules, sample1); + assert!(s1.is_err()); + assert_eq!(s1.unwrap_err().variant.message(), ERROR); + let s2 = crate::parser::parse(crate::parser::Rule::grammar_rules, sample2); + assert!(s2.is_err()); + assert_eq!(s2.unwrap_err().variant.message(), ERROR); + let s3 = crate::parser::parse(crate::parser::Rule::grammar_rules, sample3); + assert!(s3.is_err()); + assert_eq!(s3.unwrap_err().variant.message(), ERROR); + } } diff --git a/pest/src/lib.rs b/pest/src/lib.rs index d4a12e3d..30f87db6 100644 --- a/pest/src/lib.rs +++ b/pest/src/lib.rs @@ -75,7 +75,9 @@ extern crate serde; extern crate serde_json; pub use crate::parser::Parser; -pub use crate::parser_state::{state, Atomicity, Lookahead, MatchDir, ParseResult, ParserState}; +pub use crate::parser_state::{ + set_call_limit, state, Atomicity, Lookahead, MatchDir, ParseResult, ParserState, +}; pub use crate::position::Position; pub use crate::span::{Lines, LinesSpan, Span}; pub use crate::token::Token; diff --git a/pest/src/parser_state.rs b/pest/src/parser_state.rs index 934c10cc..76f0c26c 100644 --- a/pest/src/parser_state.rs +++ b/pest/src/parser_state.rs @@ -7,11 +7,14 @@ // option. All files in the project carrying such notice may not be copied, // modified, or distributed except according to those terms. +use alloc::borrow::ToOwned; use alloc::boxed::Box; use alloc::rc::Rc; use alloc::vec; use alloc::vec::Vec; +use core::num::NonZeroUsize; use core::ops::Range; +use core::sync::atomic::{AtomicUsize, Ordering}; use crate::error::{Error, ErrorVariant}; use crate::iterators::{pairs, QueueableToken}; @@ -50,6 +53,49 @@ pub enum MatchDir { TopToBottom, } +static CALL_LIMIT: AtomicUsize = AtomicUsize::new(0); + +/// Sets the maximum call limit for the parser state +/// to prevent stack overflows or excessive execution times +/// in some grammars. +/// If set, the calls are tracked as a running total +/// over all non-terminal rules that can nest closures +/// (which are passed to transform the parser state). +/// +/// # Arguments +/// +/// * `limit` - The maximum number of calls. If None, +/// the number of calls is unlimited. +pub fn set_call_limit(limit: Option) { + CALL_LIMIT.store(limit.map(|f| f.get()).unwrap_or(0), Ordering::Relaxed); +} + +#[derive(Debug)] +struct CallLimitTracker { + current_call_limit: Option<(usize, usize)>, +} + +impl Default for CallLimitTracker { + fn default() -> Self { + let limit = CALL_LIMIT.load(Ordering::Relaxed); + let current_call_limit = if limit > 0 { Some((0, limit)) } else { None }; + Self { current_call_limit } + } +} + +impl CallLimitTracker { + fn limit_reached(&self) -> bool { + self.current_call_limit + .map_or(false, |(current, limit)| current >= limit) + } + + fn increment_depth(&mut self) { + if let Some((current, _)) = &mut self.current_call_limit { + *current += 1; + } + } +} + /// The complete state of a [`Parser`]. /// /// [`Parser`]: trait.Parser.html @@ -63,6 +109,7 @@ pub struct ParserState<'i, R: RuleType> { attempt_pos: usize, atomicity: Atomicity, stack: Stack>, + call_tracker: CallLimitTracker, } /// Creates a `ParserState` from a `&str`, supplying it to a closure `f`. @@ -86,16 +133,23 @@ where Ok(pairs::new(Rc::new(state.queue), input, 0, len)) } Err(mut state) => { - state.pos_attempts.sort(); - state.pos_attempts.dedup(); - state.neg_attempts.sort(); - state.neg_attempts.dedup(); - - Err(Error::new_from_pos( + let variant = if state.reached_call_limit() { + ErrorVariant::CustomError { + message: "call limit reached".to_owned(), + } + } else { + state.pos_attempts.sort(); + state.pos_attempts.dedup(); + state.neg_attempts.sort(); + state.neg_attempts.dedup(); ErrorVariant::ParsingError { positives: state.pos_attempts.clone(), negatives: state.neg_attempts.clone(), - }, + } + }; + + Err(Error::new_from_pos( + variant, // TODO(performance): Guarantee state.attempt_pos is a valid position position::Position::new(input, state.attempt_pos).unwrap(), )) @@ -124,6 +178,7 @@ impl<'i, R: RuleType> ParserState<'i, R> { attempt_pos: 0, atomicity: Atomicity::NonAtomic, stack: Stack::new(), + call_tracker: Default::default(), }) } @@ -170,6 +225,21 @@ impl<'i, R: RuleType> ParserState<'i, R> { self.atomicity } + #[inline] + fn inc_call_check_limit(mut self: Box) -> ParseResult> { + if self.call_tracker.limit_reached() { + self.queue.clear(); + return Err(self); + } + self.call_tracker.increment_depth(); + Ok(self) + } + + #[inline] + fn reached_call_limit(&self) -> bool { + self.call_tracker.limit_reached() + } + /// Wrapper needed to generate tokens. This will associate the `R` type rule to the closure /// meant to match the rule. /// @@ -195,6 +265,7 @@ impl<'i, R: RuleType> ParserState<'i, R> { where F: FnOnce(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; let actual_pos = self.position.pos(); let index = self.queue.len(); @@ -359,10 +430,11 @@ impl<'i, R: RuleType> ParserState<'i, R> { /// assert_eq!(pairs.len(), 0); /// ``` #[inline] - pub fn sequence(self: Box, f: F) -> ParseResult> + pub fn sequence(mut self: Box, f: F) -> ParseResult> where F: FnOnce(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; let token_index = self.queue.len(); let initial_pos = self.position; @@ -408,10 +480,11 @@ impl<'i, R: RuleType> ParserState<'i, R> { /// assert_eq!(result.unwrap().position().pos(), 0); /// ``` #[inline] - pub fn repeat(self: Box, mut f: F) -> ParseResult> + pub fn repeat(mut self: Box, mut f: F) -> ParseResult> where F: FnMut(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; let mut result = f(self); loop { @@ -449,10 +522,11 @@ impl<'i, R: RuleType> ParserState<'i, R> { /// assert!(result.is_ok()); /// ``` #[inline] - pub fn optional(self: Box, f: F) -> ParseResult> + pub fn optional(mut self: Box, f: F) -> ParseResult> where F: FnOnce(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; match f(self) { Ok(state) | Err(state) => Ok(state), } @@ -730,6 +804,7 @@ impl<'i, R: RuleType> ParserState<'i, R> { where F: FnOnce(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; let initial_lookahead = self.lookahead; self.lookahead = if is_positive { @@ -797,6 +872,7 @@ impl<'i, R: RuleType> ParserState<'i, R> { where F: FnOnce(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; let initial_atomicity = self.atomicity; let should_toggle = self.atomicity != atomicity; @@ -841,10 +917,11 @@ impl<'i, R: RuleType> ParserState<'i, R> { /// assert_eq!(result.unwrap().position().pos(), 1); /// ``` #[inline] - pub fn stack_push(self: Box, f: F) -> ParseResult> + pub fn stack_push(mut self: Box, f: F) -> ParseResult> where F: FnOnce(Box) -> ParseResult>, { + self = self.inc_call_check_limit()?; let start = self.position; let result = f(self);