From 3358629dd1da63be117716b33e8bf32a22c13db9 Mon Sep 17 00:00:00 2001 From: Ethiraric Date: Sat, 19 Oct 2024 04:14:50 +0200 Subject: [PATCH] Fix infinite loop on `{...`. --- parser/src/scanner.rs | 20 +++++++++++++++----- parser/tests/issues.rs | 11 +++++++++++ parser/tests/yaml-test-suite.rs | 3 ++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/parser/src/scanner.rs b/parser/src/scanner.rs index 3fcbeb0..0509181 100644 --- a/parser/src/scanner.rs +++ b/parser/src/scanner.rs @@ -2177,7 +2177,7 @@ impl Scanner { loop { self.input.lookahead(4); if self.input.next_is_document_end() - || (self.input.next_is_document_start() && self.leading_whitespace) + || (self.leading_whitespace && self.input.next_is_document_start()) || self.input.peek() == '#' { break; @@ -2293,10 +2293,20 @@ impl Scanner { self.allow_simple_key(); } - Ok(Token( - Span::new(start_mark, end_mark), - TokenType::Scalar(TScalarStyle::Plain, string), - )) + if string.is_empty() { + // `fetch_plain_scalar` must absolutely consume at least one byte. Otherwise, + // `fetch_next_token` will never stop calling it. An empty plain scalar may happen with + // erroneous inputs such as "{...". + Err(ScanError::new_str( + start_mark, + "unexpected end of plain scalar", + )) + } else { + Ok(Token( + Span::new(start_mark, end_mark), + TokenType::Scalar(TScalarStyle::Plain, string), + )) + } } fn fetch_key(&mut self) -> ScanResult { diff --git a/parser/tests/issues.rs b/parser/tests/issues.rs index e8e9d38..d056d6f 100644 --- a/parser/tests/issues.rs +++ b/parser/tests/issues.rs @@ -214,6 +214,17 @@ fn test_issue14() { ); } +#[test] +fn test_issue14_v2() { + let s = "{..."; + let Err(error) = run_parser(s) else { panic!() }; + assert_eq!(error.info(), "unexpected end of plain scalar"); + assert_eq!( + error.to_string(), + "unexpected end of plain scalar at byte 1 line 1 column 2" + ); +} + #[test] fn test_issue13() { // The following input creates an infinite loop. diff --git a/parser/tests/yaml-test-suite.rs b/parser/tests/yaml-test-suite.rs index 554bac3..866ba16 100644 --- a/parser/tests/yaml-test-suite.rs +++ b/parser/tests/yaml-test-suite.rs @@ -94,7 +94,8 @@ fn load_tests_from_file(entry: &DirEntry) -> Result>> { let test_name = file_name .strip_suffix(".yaml") .ok_or("unexpected filename")?; - let tests = Yaml::load_from_str(&fs::read_to_string(entry.path())?)?; + let tests = Yaml::load_from_str(&fs::read_to_string(entry.path())?) + .map_err(|e| format!("While reading {file_name}: {e}"))?; let tests = tests[0].as_vec().ok_or("no test list found in file")?; let mut result = vec![];