Emit proper error for escape sequence overflow

Before this commit, escape sequences above std::char::MAX ('\u{10ffff}')
would overflow and cause a panic. This commit replaces an `unwrap` with
`ok_or` and a clearer error message. This message will likely change
in the future in order to better conform to the `dart-sass` implementation
which currently also fails to cleanly handle this overflow.

See https://github.com/kaj/rsass/pull/73
This commit is contained in:
ConnorSkees 2020-05-16 16:22:33 -04:00
parent eea8bdbc25
commit 223dade62b
2 changed files with 11 additions and 3 deletions

View File

@ -121,8 +121,9 @@ fn escape<I: Iterator<Item = Token>>(
Some(t) => t, Some(t) => t,
None => return Ok(String::new()), None => return Ok(String::new()),
}; };
let mut span = first.pos();
if first.kind == '\n' { if first.kind == '\n' {
return Err(("Expected escape sequence.", first.pos()).into()); return Err(("Expected escape sequence.", span).into());
} else if first.kind.is_ascii_hexdigit() { } else if first.kind.is_ascii_hexdigit() {
for _ in 0..6 { for _ in 0..6 {
let next = match toks.peek() { let next = match toks.peek() {
@ -133,16 +134,19 @@ fn escape<I: Iterator<Item = Token>>(
break; break;
} }
value *= 16; value *= 16;
span = span.merge(next.pos());
value += as_hex(toks.next().unwrap().kind) value += as_hex(toks.next().unwrap().kind)
} }
if toks.peek().is_some() && toks.peek().unwrap().kind.is_whitespace() { if toks.peek().is_some() && toks.peek().unwrap().kind.is_whitespace() {
toks.next(); toks.next();
} }
} else { } else {
value = toks.next().unwrap().kind as u32; let next = toks.next().unwrap();
span = span.merge(next.pos());
value = next.kind as u32;
} }
let c = std::char::from_u32(value).unwrap(); let c = std::char::from_u32(value).ok_or(("Invalid escape sequence.", span))?;
if (identifier_start && is_name_start(c) && !c.is_digit(10)) if (identifier_start && is_name_start(c) && !c.is_digit(10))
|| (!identifier_start && is_name(c)) || (!identifier_start && is_name(c))
{ {

View File

@ -168,3 +168,7 @@ test!(
"a {\n color: \\9;\n}\n", "a {\n color: \\9;\n}\n",
"a {\n color: \\9 ;\n}\n" "a {\n color: \\9 ;\n}\n"
); );
error!(
escape_sequence_does_not_fit_inside_char,
"a {\n color: \\110000;\n}\n", "Error: Invalid escape sequence."
);