From 6f81a7fd077470ff1bb9210621b3da53ffcc93bd Mon Sep 17 00:00:00 2001 From: adumbidiot Date: Tue, 4 Feb 2020 17:14:22 -0800 Subject: [PATCH 1/4] Fixed more Lexer Panics --- src/lib/syntax/lexer.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/lib/syntax/lexer.rs b/src/lib/syntax/lexer.rs index f2cbb3c9941..a74f25397ec 100644 --- a/src/lib/syntax/lexer.rs +++ b/src/lib/syntax/lexer.rs @@ -15,7 +15,7 @@ use std::{ macro_rules! vop { ($this:ident, $assign_op:expr, $op:expr) => ({ - let preview = $this.preview_next().expect("Could not preview next value"); + let preview = $this.preview_next().ok_or_else(|| LexerError::new("Could not preview next value"))?; match preview { '=' => { $this.next(); @@ -25,7 +25,7 @@ macro_rules! vop { } }); ($this:ident, $assign_op:expr, $op:expr, {$($case:pat => $block:expr), +}) => ({ - let preview = $this.preview_next().expect("Could not preview next value"); + let preview = $this.preview_next().ok_or_else(|| LexerError::new("Could not preview next value"))?; match preview { '=' => { $this.next(); @@ -39,7 +39,7 @@ macro_rules! vop { } }); ($this:ident, $op:expr, {$($case:pat => $block:expr),+}) => { - let preview = $this.preview_next().expect("Could not preview next value"); + let preview = $this.preview_next().ok_or_else(|| LexerError::new("Could not preview next value"))?; match preview { $($case => { $this.next()?; @@ -248,6 +248,9 @@ impl<'a> Lexer<'a> { '"' | '\'' => { let mut buf = String::new(); loop { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } match self.next() { '\'' if ch == '\'' => { break; @@ -256,6 +259,9 @@ impl<'a> Lexer<'a> { break; } '\\' => { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } let escape = self.next(); if escape != '\n' { let escaped_ch = match escape { @@ -268,6 +274,9 @@ impl<'a> Lexer<'a> { 'x' => { let mut nums = String::with_capacity(2); for _ in 0_u8..2 { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } nums.push(self.next()); } self.column_number += 2; @@ -302,6 +311,9 @@ impl<'a> Lexer<'a> { }; let c = from_u32(as_num).ok_or_else(|| LexerError::new("Invalid Unicode escape sequence"))?; + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } self.next(); // '}' self.column_number += (s.len() as u64).wrapping_add(3); @@ -395,11 +407,11 @@ impl<'a> Lexer<'a> { } } if gone_decimal { - u64::from_str(&buf).expect("Could not convert value to u64") + u64::from_str(&buf).map_err(|_e| LexerError::new("Could not convert value to u64"))? } else if buf.is_empty() { 0 } else { - u64::from_str_radix(&buf, 8).expect("Could not convert value to u64") + u64::from_str_radix(&buf, 8).map_err(|_e| LexerError::new("Could not convert value to u64"))? } } Some(_) => { @@ -517,6 +529,9 @@ impl<'a> Lexer<'a> { '*' => { let mut buf = String::new(); loop { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated Multiline Comment")); + } match self.next() { '*' => { if self.next_is('/') { @@ -551,6 +566,9 @@ impl<'a> Lexer<'a> { // escape sequence Some('\\') => { body.push('\\'); + if self.preview_next().is_none() { + break; + } match self.next() { // newline not allowed in regex literal '\n' | '\r' | '\u{2028}' | '\u{2029}' => break, From 019033eff066e8c6ba9456139690eb214a0bf61d Mon Sep 17 00:00:00 2001 From: Jason Williams Date: Fri, 14 Feb 2020 12:34:45 +0000 Subject: [PATCH 2/4] cargo update --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08887a516a9..b7806729d90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "Boa" -version = "0.5.1" +version = "0.6.0" dependencies = [ "criterion", "gc", @@ -68,7 +68,7 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "boa_cli" -version = "0.1.0" +version = "0.6.0" dependencies = [ "Boa", "structopt", From 0cb6d7403ef09920d37f4a465d6068d714e4b5a2 Mon Sep 17 00:00:00 2001 From: Jason Williams <936006+jasonwilliams@users.noreply.github.com> Date: Fri, 14 Feb 2020 16:22:56 +0000 Subject: [PATCH 3/4] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 197d00895a9..785a30345de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -# [# 0.6.0 (2020-14-02) - Migration to Workspace Architechure + lexer/parser improvements](https://github.com/jasonwilliams/boa/compare/v0.5.1...HEAD) +# [# 0.6.0 (2020-02-14) - Migration to Workspace Architechure + lexer/parser improvements](https://github.com/jasonwilliams/boa/compare/v0.5.1...HEAD) The lexer has had several fixes in this release, including how it parses numbers, scientific notation should be improved. On top of that the lexer no longer panics on errors including Syntax Errors (thanks @adumbidiot), instead you get some output on where the error happened. From d9924659cf88f313c75255fa39df411fa5015b8e Mon Sep 17 00:00:00 2001 From: adumbidiot Date: Tue, 4 Feb 2020 17:14:22 -0800 Subject: [PATCH 4/4] Fixed more Lexer Panics --- boa/src/syntax/lexer.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/boa/src/syntax/lexer.rs b/boa/src/syntax/lexer.rs index 04ee239b821..d961b1c9765 100644 --- a/boa/src/syntax/lexer.rs +++ b/boa/src/syntax/lexer.rs @@ -15,7 +15,7 @@ use std::{ macro_rules! vop { ($this:ident, $assign_op:expr, $op:expr) => ({ - let preview = $this.preview_next().expect("Could not preview next value"); + let preview = $this.preview_next().ok_or_else(|| LexerError::new("Could not preview next value"))?; match preview { '=' => { $this.next(); @@ -25,7 +25,7 @@ macro_rules! vop { } }); ($this:ident, $assign_op:expr, $op:expr, {$($case:pat => $block:expr), +}) => ({ - let preview = $this.preview_next().expect("Could not preview next value"); + let preview = $this.preview_next().ok_or_else(|| LexerError::new("Could not preview next value"))?; match preview { '=' => { $this.next(); @@ -39,7 +39,7 @@ macro_rules! vop { } }); ($this:ident, $op:expr, {$($case:pat => $block:expr),+}) => { - let preview = $this.preview_next().expect("Could not preview next value"); + let preview = $this.preview_next().ok_or_else(|| LexerError::new("Could not preview next value"))?; match preview { $($case => { $this.next()?; @@ -248,6 +248,9 @@ impl<'a> Lexer<'a> { '"' | '\'' => { let mut buf = String::new(); loop { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } match self.next() { '\'' if ch == '\'' => { break; @@ -256,6 +259,9 @@ impl<'a> Lexer<'a> { break; } '\\' => { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } let escape = self.next(); if escape != '\n' { let escaped_ch = match escape { @@ -268,6 +274,9 @@ impl<'a> Lexer<'a> { 'x' => { let mut nums = String::with_capacity(2); for _ in 0_u8..2 { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } nums.push(self.next()); } self.column_number += 2; @@ -302,6 +311,9 @@ impl<'a> Lexer<'a> { }; let c = from_u32(as_num).ok_or_else(|| LexerError::new("Invalid Unicode escape sequence"))?; + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated String")); + } self.next(); // '}' self.column_number += (s.len() as u64).wrapping_add(3); @@ -395,11 +407,11 @@ impl<'a> Lexer<'a> { } } if gone_decimal { - u64::from_str(&buf).expect("Could not convert value to u64") + u64::from_str(&buf).map_err(|_e| LexerError::new("Could not convert value to u64"))? } else if buf.is_empty() { 0 } else { - u64::from_str_radix(&buf, 8).expect("Could not convert value to u64") + u64::from_str_radix(&buf, 8).map_err(|_e| LexerError::new("Could not convert value to u64"))? } } Some(_) => { @@ -531,6 +543,9 @@ impl<'a> Lexer<'a> { '*' => { let mut buf = String::new(); loop { + if self.preview_next().is_none() { + return Err(LexerError::new("Unterminated Multiline Comment")); + } match self.next() { '*' => { if self.next_is('/') { @@ -565,6 +580,9 @@ impl<'a> Lexer<'a> { // escape sequence Some('\\') => { body.push('\\'); + if self.preview_next().is_none() { + break; + } match self.next() { // newline not allowed in regex literal '\n' | '\r' | '\u{2028}' | '\u{2029}' => break,