From 6215924049ba7a6fb860150ab2720c34e3acc36a Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 31 Dec 2021 17:31:49 +0100 Subject: [PATCH] move fuzzing code to lib --- fuzz/Cargo.toml | 14 +++++-- fuzz/fuzz_targets/{lex.rs => compiler.rs} | 3 +- fuzz/fuzz_targets/lex_parse.rs | 10 ----- fuzz/fuzz_targets/lexer.rs | 6 +++ fuzz/fuzz_targets/parser.rs | 6 +++ src/lib.rs | 35 ++++++++++++++++++ src/vm.rs | 45 ++++++++++++++++++++--- test.dil | 6 ++- 8 files changed, 102 insertions(+), 23 deletions(-) rename fuzz/fuzz_targets/{lex.rs => compiler.rs} (54%) delete mode 100644 fuzz/fuzz_targets/lex_parse.rs create mode 100644 fuzz/fuzz_targets/lexer.rs create mode 100644 fuzz/fuzz_targets/parser.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 99832a3..1075b15 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -19,13 +19,19 @@ path = ".." members = ["."] [[bin]] -name = "lex" -path = "fuzz_targets/lex.rs" +name = "lexer" +path = "fuzz_targets/lexer.rs" test = false doc = false [[bin]] -name = "lex_parse" -path = "fuzz_targets/lex_parse.rs" +name = "parser" +path = "fuzz_targets/parser.rs" +test = false +doc = false + +[[bin]] +name = "compiler" +path = "fuzz_targets/compiler.rs" test = false doc = false diff --git a/fuzz/fuzz_targets/lex.rs b/fuzz/fuzz_targets/compiler.rs similarity index 54% rename from fuzz/fuzz_targets/lex.rs rename to fuzz/fuzz_targets/compiler.rs index a1ab5ec..4d40f9b 100644 --- a/fuzz/fuzz_targets/lex.rs +++ b/fuzz/fuzz_targets/compiler.rs @@ -2,6 +2,5 @@ use libfuzzer_sys::fuzz_target; fuzz_target!(|data: String| { - let lexer = dilaria::Lexer::new(&data); - for _ in lexer {} + dilaria::_fuzz_compile(&data); }); diff --git a/fuzz/fuzz_targets/lex_parse.rs b/fuzz/fuzz_targets/lex_parse.rs deleted file mode 100644 index c330781..0000000 --- a/fuzz/fuzz_targets/lex_parse.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![no_main] -use libfuzzer_sys::fuzz_target; - -fuzz_target!(|data: String| { - let ast_alloc = dilaria::Bump::new(); - - let lexer = dilaria::Lexer::new(&data); - - let _ast = dilaria::parse(lexer, &ast_alloc); -}); diff --git a/fuzz/fuzz_targets/lexer.rs b/fuzz/fuzz_targets/lexer.rs new file mode 100644 index 0000000..1d752ae --- /dev/null +++ b/fuzz/fuzz_targets/lexer.rs @@ -0,0 +1,6 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: String| { + dilaria::_fuzz_lex(&data); +}); diff --git a/fuzz/fuzz_targets/parser.rs b/fuzz/fuzz_targets/parser.rs new file mode 100644 index 0000000..71157b1 --- /dev/null +++ b/fuzz/fuzz_targets/parser.rs @@ -0,0 +1,6 @@ +#![no_main] +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: String| { + dilaria::_fuzz_parse(&data); +}); diff --git a/src/lib.rs b/src/lib.rs index c61cb4c..14ac4dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,3 +64,38 @@ fn process_ast(program: &str, ast: Program, mut runtime: RtAlloc) { Err(err) => errors::display_error(program, err), } } + +// have the code here and not in the fuzzer, it's easier to find when it breaks like this + +#[doc(hidden)] +pub fn _fuzz_compile(program: &str) { + // SAFETY: Just this scope + let mut runtime = unsafe { RtAlloc::new() }; + let ast_alloc = Bump::new(); + + let lexer = lex::Lexer::new(program, &mut runtime); + let ast = parse::parse(lexer, &ast_alloc); + + if let Ok(ast) = ast { + let bytecode_alloc = Bump::new(); + let _bytecode = compile::compile(&ast, &bytecode_alloc, &mut runtime); + } +} + +#[doc(hidden)] +pub fn _fuzz_parse(program: &str) { + // SAFETY: Just this scope + let mut runtime = unsafe { RtAlloc::new() }; + let ast_alloc = Bump::new(); + + let lexer = lex::Lexer::new(program, &mut runtime); + let _ast = parse::parse(lexer, &ast_alloc); +} + +#[doc(hidden)] +pub fn _fuzz_lex(program: &str) { + // SAFETY: Just this scope + let mut runtime = unsafe { RtAlloc::new() }; + let lexer = lex::Lexer::new(program, &mut runtime); + for _ in lexer {} +} diff --git a/src/vm.rs b/src/vm.rs index 43e2227..fc27fc0 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -34,6 +34,9 @@ const fn _check_val_size() { } } +const TRUE: Value = Value::Bool(true); +const FALSE: Value = Value::Bool(false); + struct Vm<'bc> { _blocks: &'bc [FnBlock<'bc>], current: &'bc FnBlock<'bc>, @@ -100,12 +103,42 @@ impl<'bc> Vm<'bc> { (Value::Bool(a), Value::Bool(b)) => Ok(Value::Bool(a || b)), _ => Err("bad type"), })?, - Instr::CmpGreater => todo!(), - Instr::CmpGreaterEq => todo!(), - Instr::CmpLess => todo!(), - Instr::CmpLessEq => todo!(), - Instr::CmpEq => todo!(), - Instr::CmpNotEq => todo!(), + Instr::CmpGreater => self.bin_op(|lhs, rhs| match (lhs, rhs) { + (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a > b)), + (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() > b.as_str())), + _ => Err("bad type"), + })?, + Instr::CmpGreaterEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { + (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a >= b)), + (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() >= b.as_str())), + _ => Err("bad type"), + })?, + Instr::CmpLess => self.bin_op(|lhs, rhs| match (lhs, rhs) { + (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a < b)), + (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() < b.as_str())), + _ => Err("bad type"), + })?, + Instr::CmpLessEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { + (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a <= b)), + (Value::String(a), Value::String(b)) => Ok(Value::Bool(a.as_str() <= b.as_str())), + _ => Err("bad type"), + })?, + Instr::CmpEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { + (Value::Null, Value::Null) => Ok(TRUE), + (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a == b)), + (Value::String(a), Value::String(b)) => Ok(Value::Bool(a == b)), + (Value::Object(_a), Value::Object(_b)) => todo!(), + (Value::Array, Value::Array) => Ok(TRUE), + _ => Err("bad type"), + })?, + Instr::CmpNotEq => self.bin_op(|lhs, rhs| match (lhs, rhs) { + (Value::Null, Value::Null) => Ok(FALSE), + (Value::Num(a), Value::Num(b)) => Ok(Value::Bool(a != b)), + (Value::String(a), Value::String(b)) => Ok(Value::Bool(a != b)), + (Value::Object(_a), Value::Object(_b)) => todo!(), + (Value::Array, Value::Array) => Ok(FALSE), + _ => Err("bad type"), + })?, Instr::Print => { let val = self.stack.pop().unwrap(); println!("{}", val); diff --git a/test.dil b/test.dil index 05210f6..4e16444 100644 --- a/test.dil +++ b/test.dil @@ -1 +1,5 @@ -print "hi brit"; \ No newline at end of file +print "hi"; + +let is_bigger = "hallo" > "a"; + +print (not is_bigger) or true; \ No newline at end of file