diff --git a/Cargo.toml b/Cargo.toml index f48a848b..414003dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cssparser" -version = "0.7.1" +version = "0.7.2" authors = [ "Simon Sapin " ] description = "Rust implementation of CSS Syntax Level 3" diff --git a/src/parser.rs b/src/parser.rs index 6abe2b34..9a1ef3d6 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -691,15 +691,22 @@ impl<'i, 't> Parser<'i, 't> { } -/// Return value indicates whether the end of the input was reached. fn consume_until_end_of_block(block_type: BlockType, tokenizer: &mut Tokenizer) { + let mut stack = vec![block_type]; + // FIXME: have a special-purpose tokenizer method for this that does less work. while let Ok(ref token) = tokenizer.next() { - if BlockType::closing(token) == Some(block_type) { - return + if let Some(b) = BlockType::closing(token) { + if *stack.last().unwrap() == b { + stack.pop(); + if stack.is_empty() { + return; + } + } } + if let Some(block_type) = BlockType::opening(token) { - consume_until_end_of_block(block_type, tokenizer); + stack.push(block_type); } } } diff --git a/src/tests.rs b/src/tests.rs index ab85f418..ba824399 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -603,6 +603,16 @@ fn unquoted_url(b: &mut Bencher) { struct JsonParser; +#[test] +fn no_stack_overflow_multiple_nested_blocks() { + let mut input: String = "{{".into(); + for _ in 0..20 { + let dup = input.clone(); + input.push_str(&dup); + } + let mut input = Parser::new(&input); + while let Ok(..) = input.next() { } +} impl DeclarationParser for JsonParser { type Declaration = Json;