diff --git a/saphyr/src/scanner.rs b/saphyr/src/scanner.rs index 8919c4a..56496d3 100644 --- a/saphyr/src/scanner.rs +++ b/saphyr/src/scanner.rs @@ -149,7 +149,7 @@ pub struct Scanner { simple_keys: Vec, indent: isize, indents: Vec, - flow_level: usize, + flow_level: u8, tokens_parsed: usize, token_available: bool, } @@ -906,7 +906,7 @@ impl> Scanner { // The indicators '[' and '{' may start a simple key. try!(self.save_simple_key()); - self.increase_flow_level(); + self.increase_flow_level()?; self.allow_simple_key(); @@ -941,9 +941,11 @@ impl> Scanner { Ok(()) } - fn increase_flow_level(&mut self) { + fn increase_flow_level(&mut self) -> ScanResult { self.simple_keys.push(SimpleKey::new(Marker::new(0,0,0))); - self.flow_level += 1; + self.flow_level = self.flow_level.checked_add(1) + .ok_or_else(|| ScanError::new(self.mark, "Recursion limit exceeded"))?; + Ok(()) } fn decrease_flow_level(&mut self) { if self.flow_level > 0 { diff --git a/saphyr/src/yaml.rs b/saphyr/src/yaml.rs index a7ed23c..f5967b0 100644 --- a/saphyr/src/yaml.rs +++ b/saphyr/src/yaml.rs @@ -695,4 +695,16 @@ subcommands3: assert!(doc["subcommands2"][0]["server"].as_hash().is_some()); assert!(doc["subcommands3"][0]["server"].as_hash().is_some()); } + + #[test] + fn test_recursion_depth_check_objects() { + let s = "{a:".repeat(10_000) + &"}".repeat(10_000); + assert!(YamlLoader::load_from_str(&s).is_err()); + } + + #[test] + fn test_recursion_depth_check_arrays() { + let s = "[".repeat(10_000) + &"]".repeat(10_000); + assert!(YamlLoader::load_from_str(&s).is_err()); + } }