diff --git a/cranelift/isle/Cargo.lock b/cranelift/isle/Cargo.lock index 6a0f0849c0..3e8e8cb497 100644 --- a/cranelift/isle/Cargo.lock +++ b/cranelift/isle/Cargo.lock @@ -115,6 +115,15 @@ dependencies = [ "log", ] +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "log", +] + [[package]] name = "gimli" version = "0.25.0" @@ -158,15 +167,17 @@ dependencies = [ name = "isle-fuzz" version = "0.0.0" dependencies = [ + "env_logger 0.9.0", "isle", "libfuzzer-sys", + "log", ] [[package]] name = "islec" version = "0.1.0" dependencies = [ - "env_logger", + "env_logger 0.8.4", "isle", "log", "miette", diff --git a/cranelift/isle/fuzz/Cargo.toml b/cranelift/isle/fuzz/Cargo.toml index dbfb2ddb9a..bec0b681b6 100644 --- a/cranelift/isle/fuzz/Cargo.toml +++ b/cranelift/isle/fuzz/Cargo.toml @@ -9,8 +9,10 @@ edition = "2018" cargo-fuzz = true [dependencies] +env_logger = { version = "0.9.0", default-features = false } isle = { path = "../isle" } libfuzzer-sys = "0.4" +log = "0.4.14" [[bin]] name = "parse" diff --git a/cranelift/isle/fuzz/fuzz_targets/parse.rs b/cranelift/isle/fuzz/fuzz_targets/parse.rs index 747bb21e20..73cee40e87 100644 --- a/cranelift/isle/fuzz/fuzz_targets/parse.rs +++ b/cranelift/isle/fuzz/fuzz_targets/parse.rs @@ -3,8 +3,15 @@ use libfuzzer_sys::fuzz_target; fuzz_target!(|s: &str| { - if let Ok(lexer) = isle::lexer::Lexer::from_str(s, "fuzz-input.isle") { + let _ = env_logger::try_init(); + + let lexer = isle::lexer::Lexer::from_str(s, "fuzz-input.isle"); + log::debug!("lexer = {:?}", lexer); + + if let Ok(lexer) = lexer { let mut parser = isle::parser::Parser::new(lexer); - let _ = parser.parse_defs(); + + let defs = parser.parse_defs(); + log::debug!("defs = {:?}", defs); } }); diff --git a/cranelift/isle/isle/src/lexer.rs b/cranelift/isle/isle/src/lexer.rs index c247c0c3d7..f123b1a9de 100644 --- a/cranelift/isle/isle/src/lexer.rs +++ b/cranelift/isle/isle/src/lexer.rs @@ -237,6 +237,7 @@ impl<'a> Lexer<'a> { let end = self.pos.offset; let s = std::str::from_utf8(&self.buf[start..end]) .expect("Only ASCII characters, should be UTF-8"); + debug_assert!(!s.is_empty()); Ok(Some((start_pos, Token::Symbol(s.to_string())))) } c if (c >= b'0' && c <= b'9') || c == b'-' => { diff --git a/cranelift/isle/isle/src/parser.rs b/cranelift/isle/isle/src/parser.rs index 0cad0387d3..1ad29881ec 100644 --- a/cranelift/isle/isle/src/parser.rs +++ b/cranelift/isle/isle/src/parser.rs @@ -12,9 +12,6 @@ pub struct Parser<'a> { lexer: Lexer<'a>, } -/// Either `Ok(T)` or an `Err(isle::Error)`. -pub type ParseResult = std::result::Result; - impl<'a> Parser<'a> { /// Construct a new parser from the given lexer. pub fn new(lexer: Lexer<'a>) -> Parser<'a> { @@ -32,7 +29,7 @@ impl<'a> Parser<'a> { } } - fn take bool>(&mut self, f: F) -> ParseResult { + fn take bool>(&mut self, f: F) -> Result { if let Some(&(pos, ref peek)) = self.lexer.peek() { if !f(peek) { return Err(self.error(pos, format!("Unexpected token {:?}", peek))); @@ -89,27 +86,27 @@ impl<'a> Parser<'a> { }) } - fn lparen(&mut self) -> ParseResult<()> { + fn lparen(&mut self) -> Result<()> { self.take(|tok| *tok == Token::LParen).map(|_| ()) } - fn rparen(&mut self) -> ParseResult<()> { + fn rparen(&mut self) -> Result<()> { self.take(|tok| *tok == Token::RParen).map(|_| ()) } - fn at(&mut self) -> ParseResult<()> { + fn at(&mut self) -> Result<()> { self.take(|tok| *tok == Token::At).map(|_| ()) } - fn lt(&mut self) -> ParseResult<()> { + fn lt(&mut self) -> Result<()> { self.take(|tok| *tok == Token::Lt).map(|_| ()) } - fn symbol(&mut self) -> ParseResult { + fn symbol(&mut self) -> Result { match self.take(|tok| tok.is_sym())? { Token::Symbol(s) => Ok(s), _ => unreachable!(), } } - fn int(&mut self) -> ParseResult { + fn int(&mut self) -> Result { match self.take(|tok| tok.is_int())? { Token::Int(i) => Ok(i), _ => unreachable!(), @@ -117,7 +114,7 @@ impl<'a> Parser<'a> { } /// Parse the top-level ISLE definitions and return their AST. - pub fn parse_defs(&mut self) -> ParseResult { + pub fn parse_defs(&mut self) -> Result { let mut defs = vec![]; while !self.lexer.eof() { defs.push(self.parse_def()?); @@ -129,7 +126,7 @@ impl<'a> Parser<'a> { }) } - fn parse_def(&mut self) -> ParseResult { + fn parse_def(&mut self) -> Result { self.lparen()?; let pos = self.pos(); let def = match &self.symbol()?[..] { @@ -146,8 +143,11 @@ impl<'a> Parser<'a> { Ok(def) } - fn str_to_ident(&self, pos: Pos, s: &str) -> ParseResult { - let first = s.chars().next().unwrap(); + fn str_to_ident(&self, pos: Pos, s: &str) -> Result { + let first = s + .chars() + .next() + .ok_or_else(|| self.error(pos, "empty symbol".into()))?; if !first.is_alphabetic() && first != '_' && first != '$' { return Err(self.error( pos, @@ -169,13 +169,13 @@ impl<'a> Parser<'a> { Ok(Ident(s.to_string(), pos)) } - fn parse_ident(&mut self) -> ParseResult { + fn parse_ident(&mut self) -> Result { let pos = self.pos(); let s = self.symbol()?; self.str_to_ident(pos, &s) } - fn parse_const(&mut self) -> ParseResult { + fn parse_const(&mut self) -> Result { let pos = self.pos(); let ident = self.parse_ident()?; if ident.0.starts_with("$") { @@ -189,7 +189,7 @@ impl<'a> Parser<'a> { } } - fn parse_type(&mut self) -> ParseResult { + fn parse_type(&mut self) -> Result { let pos = self.pos(); let name = self.parse_ident()?; let mut is_extern = false; @@ -206,7 +206,7 @@ impl<'a> Parser<'a> { }) } - fn parse_typevalue(&mut self) -> ParseResult { + fn parse_typevalue(&mut self) -> Result { let pos = self.pos(); self.lparen()?; if self.is_sym_str("primitive") { @@ -228,7 +228,7 @@ impl<'a> Parser<'a> { } } - fn parse_type_variant(&mut self) -> ParseResult { + fn parse_type_variant(&mut self) -> Result { if self.is_sym() { let pos = self.pos(); let name = self.parse_ident()?; @@ -250,7 +250,7 @@ impl<'a> Parser<'a> { } } - fn parse_type_field(&mut self) -> ParseResult { + fn parse_type_field(&mut self) -> Result { let pos = self.pos(); self.lparen()?; let name = self.parse_ident()?; @@ -259,7 +259,7 @@ impl<'a> Parser<'a> { Ok(Field { name, ty, pos }) } - fn parse_decl(&mut self) -> ParseResult { + fn parse_decl(&mut self) -> Result { let pos = self.pos(); let term = self.parse_ident()?; @@ -280,7 +280,7 @@ impl<'a> Parser<'a> { }) } - fn parse_extern(&mut self) -> ParseResult { + fn parse_extern(&mut self) -> Result { let pos = self.pos(); if self.is_sym_str("constructor") { self.symbol()?; @@ -341,7 +341,7 @@ impl<'a> Parser<'a> { } } - fn parse_etor(&mut self) -> ParseResult { + fn parse_etor(&mut self) -> Result { let pos = self.pos(); self.lparen()?; let term = self.parse_ident()?; @@ -359,7 +359,7 @@ impl<'a> Parser<'a> { }) } - fn parse_rule(&mut self) -> ParseResult { + fn parse_rule(&mut self) -> Result { let pos = self.pos(); let prio = if self.is_int() { Some(self.int()?) @@ -376,7 +376,7 @@ impl<'a> Parser<'a> { }) } - fn parse_pattern(&mut self) -> ParseResult { + fn parse_pattern(&mut self) -> Result { let pos = self.pos(); if self.is_int() { Ok(Pattern::ConstInt { @@ -433,7 +433,7 @@ impl<'a> Parser<'a> { } } - fn parse_pattern_term_arg(&mut self) -> ParseResult { + fn parse_pattern_term_arg(&mut self) -> Result { if self.is_lt() { self.lt()?; Ok(TermArgPattern::Expr(self.parse_expr()?)) @@ -442,7 +442,7 @@ impl<'a> Parser<'a> { } } - fn parse_expr(&mut self) -> ParseResult { + fn parse_expr(&mut self) -> Result { let pos = self.pos(); if self.is_lparen() { self.lparen()?; @@ -487,7 +487,7 @@ impl<'a> Parser<'a> { } } - fn parse_letdef(&mut self) -> ParseResult { + fn parse_letdef(&mut self) -> Result { let pos = self.pos(); self.lparen()?; let var = self.parse_ident()?;