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 b7b2b7c..6652abb 100644 --- a/saphyr/src/yaml.rs +++ b/saphyr/src/yaml.rs @@ -638,4 +638,16 @@ c: ~ let first = out.into_iter().next().unwrap(); assert_eq!(first[0]["important"].as_bool().unwrap(), true); } + + #[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()); + } }