From ebaffb3db325c4657e5e5df43afa018ee71ce1c5 Mon Sep 17 00:00:00 2001 From: Mingun Date: Fri, 2 Dec 2022 21:00:23 +0500 Subject: [PATCH] Fix #517: Fix swapped codes for `\r` and `\n` characters when escaping them Co-authored-by: Daniel Alley --- Changelog.md | 2 ++ src/escapei.rs | 4 +-- src/se/element.rs | 44 ++++++++++++++++---------------- src/se/simple_type.rs | 58 +++++++++++++++++++++---------------------- 4 files changed, 55 insertions(+), 53 deletions(-) diff --git a/Changelog.md b/Changelog.md index b205c9a2..ab5a9d4f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -28,6 +28,7 @@ ``` - [#514]: Fix wrong reporting `Error::EndEventMismatch` after disabling and enabling `.check_end_names` +- [#517]: Fix swapped codes for `\r` and `\n` characters when escaping them ### Misc Changes @@ -56,6 +57,7 @@ [#490]: https://github.com/tafia/quick-xml/pull/490 [#500]: https://github.com/tafia/quick-xml/issues/500 [#514]: https://github.com/tafia/quick-xml/issues/514 +[#517]: https://github.com/tafia/quick-xml/issues/517 [XML name]: https://www.w3.org/TR/xml11/#NT-Name [documentation]: https://docs.rs/quick-xml/0.27.0/quick_xml/de/index.html#difference-between-text-and-value-special-names diff --git a/src/escapei.rs b/src/escapei.rs index d1d966f3..c080ecf4 100644 --- a/src/escapei.rs +++ b/src/escapei.rs @@ -117,8 +117,8 @@ pub(crate) fn _escape bool>(raw: &str, escape_chars: F) -> Cow // in elements of xs:lists, because those characters works as // delimiters of list elements b'\t' => escaped.extend_from_slice(b" "), - b'\r' => escaped.extend_from_slice(b" "), - b'\n' => escaped.extend_from_slice(b" "), + b'\n' => escaped.extend_from_slice(b" "), + b'\r' => escaped.extend_from_slice(b" "), b' ' => escaped.extend_from_slice(b" "), _ => unreachable!( "Only '<', '>','\', '&', '\"', '\\t', '\\r', '\\n', and ' ' are escaped" diff --git a/src/se/element.rs b/src/se/element.rs index 995fa30d..f2d9d8df 100644 --- a/src/se/element.rs +++ b/src/se/element.rs @@ -627,9 +627,9 @@ mod tests { 2\ 3"); serialize_as!(seq_empty: Vec::::new() => ""); - serialize_as!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\ - with\t\r\n spaces\ + with\t\n\r spaces\ 3"); serialize_as!(tuple_struct: Tuple("first", 42) => "first\ @@ -747,7 +747,7 @@ mod tests { // Sequences are serialized separated by spaces, all spaces inside are escaped text!(seq: vec![1, 2, 3] => "1 2 3"); text!(seq_empty: Vec::::new()); - text!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> \ with spaces \ 3"); @@ -874,7 +874,7 @@ mod tests { // Sequences are serialized separated by spaces, all spaces inside are escaped text!(seq: vec![1, 2, 3] => "1 2 3"); text!(seq_empty: Vec::::new() => ""); - text!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> \ with spaces \ 3"); @@ -1001,7 +1001,7 @@ mod tests { // Sequences are serialized separated by spaces, all spaces inside are escaped text!(seq: vec![1, 2, 3] => "1 2 3"); text!(seq_empty: Vec::::new() => ""); - text!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> \ with spaces \ 3"); @@ -1123,9 +1123,9 @@ mod tests { // Note that sequences of primitives serialized without delimiters! value!(seq: vec![1, 2, 3] => "123"); value!(seq_empty: Vec::::new()); - value!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\ - with\t\r\n spaces\ + with\t\n\r spaces\ 3"); value!(tuple_struct: Tuple("first", 42) => "first42"); value!(enum_tuple: Enum::Tuple("first", 42) @@ -1237,9 +1237,9 @@ mod tests { // Note that sequences of primitives serialized without delimiters! value!(seq: vec![1, 2, 3] => "123"); value!(seq_empty: Vec::::new() => ""); - value!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\ - with\t\r\n spaces\ + with\t\n\r spaces\ 3"); value!(tuple_struct: Tuple("first", 42) => "first42"); value!(enum_tuple: Enum::Tuple("first", 42) @@ -1359,9 +1359,9 @@ mod tests { // Note that sequences of primitives serialized without delimiters! value!(seq: vec![1, 2, 3] => "123"); value!(seq_empty: Vec::::new() => ""); - value!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\ - with\t\r\n spaces\ + with\t\n\r spaces\ 3"); value!(tuple_struct: Tuple("first", 42) => "first42"); value!(enum_tuple: Enum::Tuple("first", 42) @@ -1588,9 +1588,9 @@ mod tests { 2\n\ 3"); serialize_as!(seq_empty: Vec::::new() => ""); - serialize_as!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\n\ - with\t\r\n spaces\n\ + with\t\n\r spaces\n\ 3"); serialize_as!(tuple_struct: Tuple("first", 42) => "first\n\ @@ -1708,7 +1708,7 @@ mod tests { // Sequences are serialized separated by spaces, all spaces inside are escaped text!(seq: vec![1, 2, 3] => "1 2 3"); text!(seq_empty: Vec::::new()); - text!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> \ with spaces \ 3"); @@ -1847,7 +1847,7 @@ mod tests { // Sequences are serialized separated by spaces, all spaces inside are escaped text!(seq: vec![1, 2, 3] => "1 2 3"); text!(seq_empty: Vec::::new()); - text!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> \ with spaces \ 3"); @@ -1986,7 +1986,7 @@ mod tests { // Sequences are serialized separated by spaces, all spaces inside are escaped text!(seq: vec![1, 2, 3] => "1 2 3"); text!(seq_empty: Vec::::new()); - text!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + text!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> \ with spaces \ 3"); @@ -2107,9 +2107,9 @@ mod tests { value!(seq: vec![1, 2, 3] => "1\n 2\n 3"); value!(seq_empty: Vec::::new()); - value!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\n \ - with\t\r\n spaces\n \ + with\t\n\r spaces\n \ 3"); value!(tuple_struct: Tuple("first", 42) => "first\n 42"); value!(enum_tuple: Enum::Tuple("first", 42) @@ -2233,9 +2233,9 @@ mod tests { // Note that sequences of primitives serialized without delimiters! value!(seq: vec![1, 2, 3] => "1\n 2\n 3"); value!(seq_empty: Vec::::new()); - value!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\n \ - with\t\r\n spaces\n \ + with\t\n\r spaces\n \ 3"); value!(tuple_struct: Tuple("first", 42) => "first\n 42"); value!(enum_tuple: Enum::Tuple("first", 42) @@ -2367,9 +2367,9 @@ mod tests { // Note that sequences of primitives serialized without delimiters! value!(seq: vec![1, 2, 3] => "1\n 2\n 3"); value!(seq_empty: Vec::::new()); - value!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + value!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'>\n \ - with\t\r\n spaces\n \ + with\t\n\r spaces\n \ 3"); value!(tuple_struct: Tuple("first", 42) => "first\n 42"); value!(enum_tuple: Enum::Tuple("first", 42) diff --git a/src/se/simple_type.rs b/src/se/simple_type.rs index 17f6dc0b..55832ed6 100644 --- a/src/se/simple_type.rs +++ b/src/se/simple_type.rs @@ -587,7 +587,7 @@ mod tests { #[test] fn text() { assert_eq!( - escape_item("text<\"'&> \t\r\ntext", QuoteTarget::Text, QuoteLevel::Full), + escape_item("text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Full), "text<"'&> text" ); } @@ -596,7 +596,7 @@ mod tests { fn double_quote_attr() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::DoubleQAttr, QuoteLevel::Full ), @@ -608,7 +608,7 @@ mod tests { fn single_quote_attr() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::SingleQAttr, QuoteLevel::Full ), @@ -625,7 +625,7 @@ mod tests { fn text() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Partial ), @@ -637,7 +637,7 @@ mod tests { fn double_quote_attr() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::DoubleQAttr, QuoteLevel::Partial ), @@ -649,7 +649,7 @@ mod tests { fn single_quote_attr() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::SingleQAttr, QuoteLevel::Partial ), @@ -666,7 +666,7 @@ mod tests { fn text() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Minimal ), @@ -678,7 +678,7 @@ mod tests { fn double_quote_attr() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::DoubleQAttr, QuoteLevel::Minimal ), @@ -690,7 +690,7 @@ mod tests { fn single_quote_attr() { assert_eq!( escape_item( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::SingleQAttr, QuoteLevel::Minimal ), @@ -710,8 +710,8 @@ mod tests { #[test] fn text() { assert_eq!( - escape_list("text<\"'&> \t\r\ntext", QuoteTarget::Text, QuoteLevel::Full), - "text<"'&> \t\r\ntext" + escape_list("text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Full), + "text<"'&> \t\n\rtext" ); } @@ -719,11 +719,11 @@ mod tests { fn double_quote_attr() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::DoubleQAttr, QuoteLevel::Full ), - "text<"'&> \t\r\ntext" + "text<"'&> \t\n\rtext" ); } @@ -731,11 +731,11 @@ mod tests { fn single_quote_attr() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::SingleQAttr, QuoteLevel::Full ), - "text<"'&> \t\r\ntext" + "text<"'&> \t\n\rtext" ); } } @@ -748,11 +748,11 @@ mod tests { fn text() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Partial ), - "text<\"'&> \t\r\ntext" + "text<\"'&> \t\n\rtext" ); } @@ -760,11 +760,11 @@ mod tests { fn double_quote_attr() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::DoubleQAttr, QuoteLevel::Partial ), - "text<"'&> \t\r\ntext" + "text<"'&> \t\n\rtext" ); } @@ -772,11 +772,11 @@ mod tests { fn single_quote_attr() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::SingleQAttr, QuoteLevel::Partial ), - "text<\"'&> \t\r\ntext" + "text<\"'&> \t\n\rtext" ); } } @@ -789,11 +789,11 @@ mod tests { fn text() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::Text, QuoteLevel::Minimal ), - "text<\"'&> \t\r\ntext" + "text<\"'&> \t\n\rtext" ); } @@ -801,11 +801,11 @@ mod tests { fn double_quote_attr() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::DoubleQAttr, QuoteLevel::Minimal ), - "text<"'&> \t\r\ntext" + "text<"'&> \t\n\rtext" ); } @@ -813,11 +813,11 @@ mod tests { fn single_quote_attr() { assert_eq!( escape_list( - "text<\"'&> \t\r\ntext", + "text<\"'&> \t\n\rtext", QuoteTarget::SingleQAttr, QuoteLevel::Minimal ), - "text<\"'&> \t\r\ntext" + "text<\"'&> \t\n\rtext" ); } } @@ -925,7 +925,7 @@ mod tests { err!(seq: vec![1, 2, 3] => Unsupported("sequence cannot be serialized as an `xs:list` item")); - err!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + err!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => Unsupported("tuple cannot be serialized as an `xs:list` item")); err!(tuple_struct: Tuple("first", 42) => Unsupported("tuple struct `Tuple` cannot be serialized as an `xs:list` item")); @@ -1043,7 +1043,7 @@ mod tests { serialize_as!(seq_empty: Vec::::new() => ""); serialize_as!(seq_with_1_empty_str: vec![""] => ""); serialize_as!(seq_with_2_empty_strs: vec!["", ""] => " "); - serialize_as!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize) + serialize_as!(tuple: ("<\"&'>", "with\t\n\r spaces", 3usize) => "<"&'> with spaces 3"); serialize_as!(tuple_struct: Tuple("first", 42) => "first 42"); err!(enum_tuple: Enum::Tuple("first", 42)