@@ -134,6 +134,30 @@ public function test_style_contents_are_not_escaped() {
134134 );
135135 }
136136
137+ /**
138+ * Ensures that XMP contents are not escaped, as they are not parsed like text nodes are.
139+ *
140+ * XMP contents are parsed as raw text: character references are never decoded.
141+ * Escaping the contents would change the document, e.g. a "<" would be replaced
142+ * by the literal text "<" after serializing and re-parsing.
143+ *
144+ * @ticket 65372
145+ */
146+ public function test_xmp_contents_are_not_escaped () {
147+ $ normalized = WP_HTML_Processor::normalize ( "<xmp>1 < 2 & apples > or \x00anges</xmp> " );
148+
149+ $ this ->assertSame (
150+ "<xmp>1 < 2 & apples > or \u{FFFD}anges</xmp> " ,
151+ $ normalized ,
152+ 'Should have preserved text inside an XMP element, except for replacing NULL bytes. '
153+ );
154+ $ this ->assertSame (
155+ $ normalized ,
156+ WP_HTML_Processor::normalize ( $ normalized ),
157+ 'Normalizing already-normalized XMP should not escape the raw text again. '
158+ );
159+ }
160+
137161 public function test_unexpected_closing_tags_are_removed () {
138162 $ this ->assertSame (
139163 WP_HTML_Processor::normalize ( 'one</div>two</span>three ' ),
@@ -281,6 +305,7 @@ public static function data_tokens_with_null_bytes() {
281305 'Foreign content text ' => array ( "<svg>one \x00two</svg> " , "<svg>one \u{FFFD}two</svg> " ),
282306 'SCRIPT content ' => array ( "<script>alert( \x00)</script> " , "<script>alert( \u{FFFD})</script> " ),
283307 'STYLE content ' => array ( "<style> \x00 {}</style> " , "<style> \u{FFFD} {}</style> " ),
308+ 'XMP content ' => array ( "<xmp>a \x00b</xmp> " , "<xmp>a \u{FFFD}b</xmp> " ),
284309 'Comment text ' => array ( "<!-- \x00 --> " , "<!-- \u{FFFD} --> " ),
285310 );
286311 }
0 commit comments