Fix panic on trailing backslash in string (fixes #551)

This commit is contained in:
elkowar 2022-10-01 17:24:34 +02:00
parent 37fc231761
commit f0d4f40dcf
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
2 changed files with 19 additions and 6 deletions

View file

@ -166,7 +166,7 @@ impl<'s> Lexer<'s> {
let tok_str = &self.source[self.pos..self.pos + len];
let old_pos = self.pos;
self.advance_by(len);
self.advance_by(len)?;
match LEXER_FNS[i](tok_str.to_string()) {
Token::Skip | Token::Comment => {}
token => {
@ -177,11 +177,17 @@ impl<'s> Lexer<'s> {
}
}
fn advance_by(&mut self, n: usize) {
/// Advance position by the given number of characters, respecting char boundaries. Returns `None` when n exceeds the source length
#[must_use]
fn advance_by(&mut self, n: usize) -> Option<()> {
if self.pos + n > self.source.len() {
return None;
}
self.pos += n;
while self.pos < self.source.len() && !self.source.is_char_boundary(self.pos) {
self.pos += 1;
}
Some(())
}
fn advance_until_one_of<'a>(&mut self, pat: &[&'a str]) -> Option<&'a str> {
@ -190,10 +196,10 @@ impl<'s> Lexer<'s> {
if remaining.is_empty() {
return None;
} else if let Some(matched) = pat.iter().find(|&&p| remaining.starts_with(p)) {
self.advance_by(matched.len());
self.advance_by(matched.len())?;
return Some(matched);
} else {
self.advance_by(1);
self.advance_by(1)?;
}
}
}
@ -203,7 +209,7 @@ impl<'s> Lexer<'s> {
pattern.push("\\");
match self.advance_until_one_of(pattern.as_slice()) {
Some("\\") => {
self.advance_by(1);
self.advance_by(1)?;
self.advance_until_unescaped_one_of(pat)
}
result => result,
@ -213,7 +219,7 @@ impl<'s> Lexer<'s> {
pub fn string_lit(&mut self) -> Option<Result<Sp<Vec<Sp<StrLitSegment>>>, LexicalError>> {
let quote = self.remaining().chars().next()?.to_string();
let str_lit_start = self.pos;
self.advance_by(quote.len());
self.advance_by(quote.len())?;
let mut elements = Vec::new();
let mut in_string_lit = true;
@ -308,6 +314,7 @@ mod test {
snapshot_string! {
basic => v!(r#"bar "foo""#),
digit => v!(r#"12"#),
quote_backslash_eof => v!(r#""\"#),
number_in_ident => v!(r#"foo_1_bar"#),
interpolation_1 => v!(r#" "foo ${2 * 2} bar" "#),
interpolation_nested => v!(r#" "foo ${(2 * 2) + "${5 + 5}"} bar" "#),

View file

@ -0,0 +1,6 @@
---
source: crates/simplexpr/src/parser/lexer.rs
assertion_line: 313
expression: "v!(r#\"\"\\\"#)"
---