Compare commits
4 commits
e0e84ede1c
...
3f549690c1
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f549690c1 | |||
| b0620a00d5 | |||
| 462355b6f2 | |||
| fa1582f3ad |
14 changed files with 420 additions and 34 deletions
|
|
@ -95,6 +95,10 @@
|
||||||
pkgs.cargo-flamegraph
|
pkgs.cargo-flamegraph
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
devShells.fuzz = devShells.crate.overrideAttrs (prev: {
|
||||||
|
nativeBuildInputs = [ unstableRustTarget pkgs.cargo-fuzz ];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
fuzz/.envrc
Normal file
1
fuzz/.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use flake .#fuzz
|
||||||
6
fuzz/.gitignore
vendored
Normal file
6
fuzz/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
.direnv/
|
||||||
|
|
||||||
|
target
|
||||||
|
corpus
|
||||||
|
artifacts
|
||||||
|
coverage
|
||||||
277
fuzz/Cargo.lock
generated
Normal file
277
fuzz/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,277 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotate-snippets"
|
||||||
|
version = "0.12.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74fc7650eedcb2fee505aad48491529e408f0e854c2d9f63eb86c1361b9b3f93"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"memchr",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arbitrary"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"jobserver",
|
||||||
|
"libc",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "displaydoc"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi",
|
||||||
|
"wasip2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jobserver"
|
||||||
|
version = "0.1.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.183"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libfuzzer-sys"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary",
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nomo"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"annotate-snippets",
|
||||||
|
"displaydoc",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nomo-fuzz"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"libfuzzer-sys",
|
||||||
|
"nomo",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "r-efi"
|
||||||
|
version = "5.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.149"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
"zmij",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.117"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasip2"
|
||||||
|
version = "1.0.2+wasi-0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen"
|
||||||
|
version = "0.51.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zmij"
|
||||||
|
version = "1.0.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
21
fuzz/Cargo.toml
Normal file
21
fuzz/Cargo.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "nomo-fuzz"
|
||||||
|
version = "0.0.0"
|
||||||
|
publish = false
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
cargo-fuzz = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libfuzzer-sys = "0.4"
|
||||||
|
|
||||||
|
[dependencies.nomo]
|
||||||
|
path = ".."
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "fuzz_target_1"
|
||||||
|
path = "fuzz_targets/fuzz_target_1.rs"
|
||||||
|
test = false
|
||||||
|
doc = false
|
||||||
|
bench = false
|
||||||
18
fuzz/fuzz_targets/fuzz_target_1.rs
Normal file
18
fuzz/fuzz_targets/fuzz_target_1.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use libfuzzer_sys::Corpus;
|
||||||
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
|
fuzz_target!(|data: String| -> Corpus {
|
||||||
|
let Ok(parsed) = nomo::parser::parse(data.into()) else {
|
||||||
|
return Corpus::Reject;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(ast) = nomo::ast::parse(parsed.tokens()) else {
|
||||||
|
return Corpus::Keep;
|
||||||
|
};
|
||||||
|
|
||||||
|
let _instructions = nomo::emit::emit_machine(ast);
|
||||||
|
|
||||||
|
Corpus::Keep
|
||||||
|
});
|
||||||
|
|
@ -345,6 +345,26 @@ fn parse_conditional_chain<'input>(
|
||||||
|
|
||||||
chain.push(if_block);
|
chain.push(if_block);
|
||||||
|
|
||||||
|
let content = resume_after_cut(
|
||||||
|
cut_err(inner_conditional_chain),
|
||||||
|
repeat_till(0.., any, parse_end).map(|((), _)| ()),
|
||||||
|
)
|
||||||
|
.parse_next(input)?;
|
||||||
|
|
||||||
|
chain.extend(content.into_iter().flatten());
|
||||||
|
|
||||||
|
Ok(TemplateAstExpr::ConditionalChain { chain })
|
||||||
|
})
|
||||||
|
.parse_next(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner_conditional_chain<'input>(
|
||||||
|
input: &mut Input<'input>,
|
||||||
|
) -> Result<Vec<TemplateAstExpr<'input>>, AstError> {
|
||||||
|
let mut needs_end = false;
|
||||||
|
|
||||||
|
let mut chain = vec![];
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (content, end_block): (Vec<_>, _) = repeat_till(
|
let (content, end_block): (Vec<_>, _) = repeat_till(
|
||||||
0..,
|
0..,
|
||||||
|
|
@ -366,6 +386,16 @@ fn parse_conditional_chain<'input>(
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !is_end && needs_end {
|
||||||
|
return Err(AstError::from_input(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let TemplateAstExpr::Block { expression, .. } = &end_block
|
||||||
|
&& let TemplateAstExpr::ElseConditional { expression: None } = &**expression
|
||||||
|
{
|
||||||
|
needs_end = true;
|
||||||
|
}
|
||||||
|
|
||||||
chain.push(end_block);
|
chain.push(end_block);
|
||||||
|
|
||||||
if is_end {
|
if is_end {
|
||||||
|
|
@ -373,9 +403,7 @@ fn parse_conditional_chain<'input>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TemplateAstExpr::ConditionalChain { chain })
|
Ok(chain)
|
||||||
})
|
|
||||||
.parse_next(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_conditional_if<'input>(
|
fn parse_conditional_if<'input>(
|
||||||
|
|
|
||||||
|
|
@ -123,14 +123,16 @@ fn emit_ast_expr(
|
||||||
{
|
{
|
||||||
previous_post_whitespace_content = post_whitespace_content;
|
previous_post_whitespace_content = post_whitespace_content;
|
||||||
if let Some(ws) = prev_whitespace_content {
|
if let Some(ws) = prev_whitespace_content {
|
||||||
|
let idx = end_indices.last().copied();
|
||||||
eval.insert(
|
eval.insert(
|
||||||
eval.len() - 2,
|
idx.unwrap_or(eval.len()),
|
||||||
Instruction::AppendContent {
|
Instruction::AppendContent {
|
||||||
content: ws.source().clone(),
|
content: ws.source().clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let index_index = end_indices.len() - 1;
|
if let Some(idx) = end_indices.last_mut() {
|
||||||
end_indices[index_index] += 1;
|
*idx += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let TemplateAstExpr::IfConditional { expression } = &**expression {
|
if let TemplateAstExpr::IfConditional { expression } = &**expression {
|
||||||
|
|
|
||||||
|
|
@ -383,10 +383,10 @@ fn parse_block_token<'input>(input: &mut Input<'input>) -> PResult<'input, Templ
|
||||||
"parse_block_token",
|
"parse_block_token",
|
||||||
alt((
|
alt((
|
||||||
parse_ident,
|
parse_ident,
|
||||||
parse_literal,
|
terminated(parse_literal, ident_terminator_check),
|
||||||
parse_condition_if,
|
terminated(parse_condition_if, ident_terminator_check),
|
||||||
parse_condition_else,
|
terminated(parse_condition_else, ident_terminator_check),
|
||||||
parse_end,
|
terminated(parse_end, ident_terminator_check),
|
||||||
parse_whitespace,
|
parse_whitespace,
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
18
tests/checks.rs
Normal file
18
tests/checks.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#[test]
|
||||||
|
fn check_files() {
|
||||||
|
let files = std::fs::read_dir("tests/checks/").unwrap();
|
||||||
|
|
||||||
|
for file in files {
|
||||||
|
let input = std::fs::read_to_string(file.unwrap().path()).unwrap();
|
||||||
|
|
||||||
|
let Ok(parsed) = nomo::parser::parse(input.into()) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(ast) = nomo::ast::parse(parsed.tokens()) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let _emit = nomo::emit::emit_machine(ast);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
tests/checks/long.nomo
Normal file
BIN
tests/checks/long.nomo
Normal file
Binary file not shown.
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
{{if en}}{{ end}}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{{ if t }}
|
||||||
|
{{else}}{{ else }}
|
||||||
|
{{end }}
|
||||||
|
|
@ -31,7 +31,13 @@ fn check_cases() {
|
||||||
|
|
||||||
insta::assert_debug_snapshot!("1-parsed", parsed);
|
insta::assert_debug_snapshot!("1-parsed", parsed);
|
||||||
|
|
||||||
let ast = nomo::ast::parse(parsed.tokens()).unwrap();
|
let ast = match nomo::ast::parse(parsed.tokens()) {
|
||||||
|
Ok(ast) => ast,
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("{}", err.to_report(input));
|
||||||
|
panic!("Could not evaluate ast");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
insta::assert_debug_snapshot!("2-ast", ast);
|
insta::assert_debug_snapshot!("2-ast", ast);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue