diff --git a/juniper/src/parser/lexer.rs b/juniper/src/parser/lexer.rs index ec86a2329..505046440 100644 --- a/juniper/src/parser/lexer.rs +++ b/juniper/src/parser/lexer.rs @@ -296,7 +296,11 @@ impl<'a> Lexer<'a> { len += 1; } - let escape = &self.source[start_idx..=end_idx]; + // Make sure we are on a valid char boundary. + let escape = &self + .source + .get(start_idx..=end_idx) + .ok_or_else(|| Spanning::zero_width(&self.position, LexerError::UnterminatedString))?; if len != 4 { return Err(Spanning::zero_width( diff --git a/juniper/src/parser/tests/lexer.rs b/juniper/src/parser/tests/lexer.rs index 39f3b9a6f..a08dbfaac 100644 --- a/juniper/src/parser/tests/lexer.rs +++ b/juniper/src/parser/tests/lexer.rs @@ -322,6 +322,15 @@ fn string_errors() { LexerError::UnterminatedString ) ); + + // Found by fuzzing. + assert_eq!( + tokenize_error(r#""\uɠ^A"#), + Spanning::zero_width( + &SourcePosition::new(5, 0, 5), + LexerError::UnterminatedString + ) + ); } #[test]