From 08f2327b4e47d9695431f5fe5be1309b47078ec1 Mon Sep 17 00:00:00 2001 From: xenon Date: Tue, 13 Feb 2024 18:17:12 -0500 Subject: [PATCH] - Fixed infinite loop in lexer when reading an unterminated string - Added a test to ensure unterminated strings are caught as an error by the lexer --- layout/src/gv/parser/lexer.rs | 10 ++++++---- tests/test.rs | 12 ++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/layout/src/gv/parser/lexer.rs b/layout/src/gv/parser/lexer.rs index ac7b572..1a823be 100644 --- a/layout/src/gv/parser/lexer.rs +++ b/layout/src/gv/parser/lexer.rs @@ -160,7 +160,7 @@ impl Lexer { result } - pub fn read_string(&mut self) -> String { + pub fn read_string(&mut self) -> Token { let mut result = String::new(); self.read_char(); while self.ch != '"' { @@ -173,11 +173,14 @@ impl Lexer { 'l' => '\n', _ => self.ch, } + } else if self.ch == '\0' { + // Reached EOF without completing the string + return Token::Error(self.pos); } result.push(self.ch); self.read_char(); } - result + Token::Identifier(result) } pub fn next_token(&mut self) -> Token { @@ -209,8 +212,7 @@ impl Lexer { tok = Token::Comma; } '"' => { - let value = self.read_string(); - tok = Token::Identifier(value); + tok = self.read_string(); } '-' => { self.read_char(); diff --git a/tests/test.rs b/tests/test.rs index 03959b9..f97da99 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -108,6 +108,18 @@ mod tests { assert!(matches!(lexer.next_token(), Token::EOF)); } + #[test] + fn catch_unterminated_str() { + let mut lexer = Lexer::from_string("digraph { a -> b; \" } "); + assert!(matches!(lexer.next_token(), Token::DigraphKW)); + assert!(matches!(lexer.next_token(), Token::OpenBrace)); + assert!(matches!(lexer.next_token(), Token::Identifier(_))); + assert!(matches!(lexer.next_token(), Token::ArrowRight)); + assert!(matches!(lexer.next_token(), Token::Identifier(_))); + assert!(matches!(lexer.next_token(), Token::Semicolon)); + assert!(matches!(lexer.next_token(), Token::Error(_))); + } + #[test] fn lex_program() { let program = get_sample_program2();