From 00a8629414d07c5cabb562e5d74b26cadf2bd171 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 5 Sep 2017 14:46:42 +0200 Subject: [PATCH] Fix serialization of bad-string and bad-url tokens --- Cargo.toml | 2 +- src/serializer.rs | 16 ++++++++++++++-- src/tests.rs | 20 ++++++++++++++++++++ src/tokenizer.rs | 3 ++- 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f9c221b..c409bac9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cssparser" -version = "0.20.0" +version = "0.20.1" authors = [ "Simon Sapin " ] description = "Rust implementation of CSS Syntax Level 3" diff --git a/src/serializer.rs b/src/serializer.rs index ef0bb9fa..20c64e53 100644 --- a/src/serializer.rs +++ b/src/serializer.rs @@ -122,8 +122,20 @@ impl<'a> ToCss for Token<'a> { Token::SquareBracketBlock => dest.write_str("[")?, Token::CurlyBracketBlock => dest.write_str("{")?, - Token::BadUrl(_) => dest.write_str("url()")?, - Token::BadString(_) => dest.write_str("\"\n")?, + Token::BadUrl(ref contents) => { + dest.write_str("url(")?; + dest.write_str(contents)?; + dest.write_char(')')?; + } + Token::BadString(ref value) => { + // During tokenization, an unescaped newline after a quote causes + // the token to be a BadString instead of a QuotedString. + // The BadString token ends just before the newline + // (which is in a separate WhiteSpace token), + // and therefore does not have a closing quote. + dest.write_char('"')?; + CssStringWriter::new(dest).write_str(value)?; + }, Token::CloseParenthesis => dest.write_str(")")?, Token::CloseSquareBracket => dest.write_str("]")?, Token::CloseCurlyBracket => dest.write_str("}")?, diff --git a/src/tests.rs b/src/tests.rs index ebdb3122..24242d5f 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -441,6 +441,26 @@ fn serializer(preserve_comments: bool) { }); } +#[test] +fn serialize_bad_tokens() { + let mut input = ParserInput::new("url(foo\\) b\\)ar)'ba\\'\"z\n4"); + let mut parser = Parser::new(&mut input); + + let token = parser.next().unwrap().clone(); + assert!(matches!(token, Token::BadUrl(_))); + assert_eq!(token.to_css_string(), "url(foo\\) b\\)ar)"); + + let token = parser.next().unwrap().clone(); + assert!(matches!(token, Token::BadString(_))); + assert_eq!(token.to_css_string(), "\"ba'\\\"z"); + + let token = parser.next().unwrap().clone(); + assert!(matches!(token, Token::Number { .. })); + assert_eq!(token.to_css_string(), "4"); + + assert!(parser.next().is_err()); +} + #[test] fn serialize_current_color() { let c = Color::CurrentColor; diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 9681a7f8..d9060fb7 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1289,8 +1289,9 @@ fn consume_unquoted_url<'a>(tokenizer: &mut Tokenizer<'a>) -> Result, while !tokenizer.is_eof() { match_byte! { tokenizer.next_byte_unchecked(), b')' => { + let contents = tokenizer.slice_from(start_pos).into(); tokenizer.advance(1); - break + return BadUrl(contents) } b'\\' => { tokenizer.advance(1);