Fix a panic when parsing var patterns
This commit is contained in:
committed by
Chris Fallin
parent
f2b6244b9c
commit
e3aeb850b2
13
cranelift/isle/Cargo.lock
generated
13
cranelift/isle/Cargo.lock
generated
@@ -115,6 +115,15 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
@@ -158,15 +167,17 @@ dependencies = [
|
|||||||
name = "isle-fuzz"
|
name = "isle-fuzz"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"env_logger 0.9.0",
|
||||||
"isle",
|
"isle",
|
||||||
"libfuzzer-sys",
|
"libfuzzer-sys",
|
||||||
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "islec"
|
name = "islec"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger 0.8.4",
|
||||||
"isle",
|
"isle",
|
||||||
"log",
|
"log",
|
||||||
"miette",
|
"miette",
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ edition = "2018"
|
|||||||
cargo-fuzz = true
|
cargo-fuzz = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
env_logger = { version = "0.9.0", default-features = false }
|
||||||
isle = { path = "../isle" }
|
isle = { path = "../isle" }
|
||||||
libfuzzer-sys = "0.4"
|
libfuzzer-sys = "0.4"
|
||||||
|
log = "0.4.14"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "parse"
|
name = "parse"
|
||||||
|
|||||||
@@ -3,8 +3,15 @@
|
|||||||
use libfuzzer_sys::fuzz_target;
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
fuzz_target!(|s: &str| {
|
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 mut parser = isle::parser::Parser::new(lexer);
|
||||||
let _ = parser.parse_defs();
|
|
||||||
|
let defs = parser.parse_defs();
|
||||||
|
log::debug!("defs = {:?}", defs);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ impl<'a> Lexer<'a> {
|
|||||||
let end = self.pos.offset;
|
let end = self.pos.offset;
|
||||||
let s = std::str::from_utf8(&self.buf[start..end])
|
let s = std::str::from_utf8(&self.buf[start..end])
|
||||||
.expect("Only ASCII characters, should be UTF-8");
|
.expect("Only ASCII characters, should be UTF-8");
|
||||||
|
debug_assert!(!s.is_empty());
|
||||||
Ok(Some((start_pos, Token::Symbol(s.to_string()))))
|
Ok(Some((start_pos, Token::Symbol(s.to_string()))))
|
||||||
}
|
}
|
||||||
c if (c >= b'0' && c <= b'9') || c == b'-' => {
|
c if (c >= b'0' && c <= b'9') || c == b'-' => {
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ pub struct Parser<'a> {
|
|||||||
lexer: Lexer<'a>,
|
lexer: Lexer<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Either `Ok(T)` or an `Err(isle::Error)`.
|
|
||||||
pub type ParseResult<T> = std::result::Result<T, Error>;
|
|
||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Construct a new parser from the given lexer.
|
/// Construct a new parser from the given lexer.
|
||||||
pub fn new(lexer: Lexer<'a>) -> Parser<'a> {
|
pub fn new(lexer: Lexer<'a>) -> Parser<'a> {
|
||||||
@@ -32,7 +29,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take<F: Fn(&Token) -> bool>(&mut self, f: F) -> ParseResult<Token> {
|
fn take<F: Fn(&Token) -> bool>(&mut self, f: F) -> Result<Token> {
|
||||||
if let Some(&(pos, ref peek)) = self.lexer.peek() {
|
if let Some(&(pos, ref peek)) = self.lexer.peek() {
|
||||||
if !f(peek) {
|
if !f(peek) {
|
||||||
return Err(self.error(pos, format!("Unexpected token {:?}", 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(|_| ())
|
self.take(|tok| *tok == Token::LParen).map(|_| ())
|
||||||
}
|
}
|
||||||
fn rparen(&mut self) -> ParseResult<()> {
|
fn rparen(&mut self) -> Result<()> {
|
||||||
self.take(|tok| *tok == Token::RParen).map(|_| ())
|
self.take(|tok| *tok == Token::RParen).map(|_| ())
|
||||||
}
|
}
|
||||||
fn at(&mut self) -> ParseResult<()> {
|
fn at(&mut self) -> Result<()> {
|
||||||
self.take(|tok| *tok == Token::At).map(|_| ())
|
self.take(|tok| *tok == Token::At).map(|_| ())
|
||||||
}
|
}
|
||||||
fn lt(&mut self) -> ParseResult<()> {
|
fn lt(&mut self) -> Result<()> {
|
||||||
self.take(|tok| *tok == Token::Lt).map(|_| ())
|
self.take(|tok| *tok == Token::Lt).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn symbol(&mut self) -> ParseResult<String> {
|
fn symbol(&mut self) -> Result<String> {
|
||||||
match self.take(|tok| tok.is_sym())? {
|
match self.take(|tok| tok.is_sym())? {
|
||||||
Token::Symbol(s) => Ok(s),
|
Token::Symbol(s) => Ok(s),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int(&mut self) -> ParseResult<i64> {
|
fn int(&mut self) -> Result<i64> {
|
||||||
match self.take(|tok| tok.is_int())? {
|
match self.take(|tok| tok.is_int())? {
|
||||||
Token::Int(i) => Ok(i),
|
Token::Int(i) => Ok(i),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@@ -117,7 +114,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the top-level ISLE definitions and return their AST.
|
/// Parse the top-level ISLE definitions and return their AST.
|
||||||
pub fn parse_defs(&mut self) -> ParseResult<Defs> {
|
pub fn parse_defs(&mut self) -> Result<Defs> {
|
||||||
let mut defs = vec![];
|
let mut defs = vec![];
|
||||||
while !self.lexer.eof() {
|
while !self.lexer.eof() {
|
||||||
defs.push(self.parse_def()?);
|
defs.push(self.parse_def()?);
|
||||||
@@ -129,7 +126,7 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_def(&mut self) -> ParseResult<Def> {
|
fn parse_def(&mut self) -> Result<Def> {
|
||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let def = match &self.symbol()?[..] {
|
let def = match &self.symbol()?[..] {
|
||||||
@@ -146,8 +143,11 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(def)
|
Ok(def)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn str_to_ident(&self, pos: Pos, s: &str) -> ParseResult<Ident> {
|
fn str_to_ident(&self, pos: Pos, s: &str) -> Result<Ident> {
|
||||||
let first = s.chars().next().unwrap();
|
let first = s
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| self.error(pos, "empty symbol".into()))?;
|
||||||
if !first.is_alphabetic() && first != '_' && first != '$' {
|
if !first.is_alphabetic() && first != '_' && first != '$' {
|
||||||
return Err(self.error(
|
return Err(self.error(
|
||||||
pos,
|
pos,
|
||||||
@@ -169,13 +169,13 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(Ident(s.to_string(), pos))
|
Ok(Ident(s.to_string(), pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ident(&mut self) -> ParseResult<Ident> {
|
fn parse_ident(&mut self) -> Result<Ident> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let s = self.symbol()?;
|
let s = self.symbol()?;
|
||||||
self.str_to_ident(pos, &s)
|
self.str_to_ident(pos, &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_const(&mut self) -> ParseResult<Ident> {
|
fn parse_const(&mut self) -> Result<Ident> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
if ident.0.starts_with("$") {
|
if ident.0.starts_with("$") {
|
||||||
@@ -189,7 +189,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type(&mut self) -> ParseResult<Type> {
|
fn parse_type(&mut self) -> Result<Type> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
let mut is_extern = false;
|
let mut is_extern = false;
|
||||||
@@ -206,7 +206,7 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_typevalue(&mut self) -> ParseResult<TypeValue> {
|
fn parse_typevalue(&mut self) -> Result<TypeValue> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
if self.is_sym_str("primitive") {
|
if self.is_sym_str("primitive") {
|
||||||
@@ -228,7 +228,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type_variant(&mut self) -> ParseResult<Variant> {
|
fn parse_type_variant(&mut self) -> Result<Variant> {
|
||||||
if self.is_sym() {
|
if self.is_sym() {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
@@ -250,7 +250,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type_field(&mut self) -> ParseResult<Field> {
|
fn parse_type_field(&mut self) -> Result<Field> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
@@ -259,7 +259,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(Field { name, ty, pos })
|
Ok(Field { name, ty, pos })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_decl(&mut self) -> ParseResult<Decl> {
|
fn parse_decl(&mut self) -> Result<Decl> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let term = self.parse_ident()?;
|
let term = self.parse_ident()?;
|
||||||
|
|
||||||
@@ -280,7 +280,7 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_extern(&mut self) -> ParseResult<Extern> {
|
fn parse_extern(&mut self) -> Result<Extern> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
if self.is_sym_str("constructor") {
|
if self.is_sym_str("constructor") {
|
||||||
self.symbol()?;
|
self.symbol()?;
|
||||||
@@ -341,7 +341,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_etor(&mut self) -> ParseResult<Extractor> {
|
fn parse_etor(&mut self) -> Result<Extractor> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
let term = self.parse_ident()?;
|
let term = self.parse_ident()?;
|
||||||
@@ -359,7 +359,7 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_rule(&mut self) -> ParseResult<Rule> {
|
fn parse_rule(&mut self) -> Result<Rule> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let prio = if self.is_int() {
|
let prio = if self.is_int() {
|
||||||
Some(self.int()?)
|
Some(self.int()?)
|
||||||
@@ -376,7 +376,7 @@ impl<'a> Parser<'a> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pattern(&mut self) -> ParseResult<Pattern> {
|
fn parse_pattern(&mut self) -> Result<Pattern> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
if self.is_int() {
|
if self.is_int() {
|
||||||
Ok(Pattern::ConstInt {
|
Ok(Pattern::ConstInt {
|
||||||
@@ -433,7 +433,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pattern_term_arg(&mut self) -> ParseResult<TermArgPattern> {
|
fn parse_pattern_term_arg(&mut self) -> Result<TermArgPattern> {
|
||||||
if self.is_lt() {
|
if self.is_lt() {
|
||||||
self.lt()?;
|
self.lt()?;
|
||||||
Ok(TermArgPattern::Expr(self.parse_expr()?))
|
Ok(TermArgPattern::Expr(self.parse_expr()?))
|
||||||
@@ -442,7 +442,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(&mut self) -> ParseResult<Expr> {
|
fn parse_expr(&mut self) -> Result<Expr> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
if self.is_lparen() {
|
if self.is_lparen() {
|
||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
@@ -487,7 +487,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_letdef(&mut self) -> ParseResult<LetDef> {
|
fn parse_letdef(&mut self) -> Result<LetDef> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
let var = self.parse_ident()?;
|
let var = self.parse_ident()?;
|
||||||
|
|||||||
Reference in New Issue
Block a user