diff --git a/src/wp-includes/html-api/class-wp-html-tag-processor.php b/src/wp-includes/html-api/class-wp-html-tag-processor.php index 7ca5191a0f162..32cb30b6afb82 100644 --- a/src/wp-includes/html-api/class-wp-html-tag-processor.php +++ b/src/wp-includes/html-api/class-wp-html-tag-processor.php @@ -1475,7 +1475,7 @@ private function skip_rcdata( string $tag_name ): bool { * though "textarea" is found within the text. */ $c = $html[ $at ]; - if ( ' ' !== $c && "\t" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { + if ( ' ' !== $c && "\t" !== $c && "\f" !== $c && "\r" !== $c && "\n" !== $c && '/' !== $c && '>' !== $c ) { continue; } diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index 66e01dbdbed3e..8733f5718ba6c 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -2369,6 +2369,52 @@ public static function data_script_tag(): Generator { yield 'Script tag double-escaped with array( "", false ); } + /** + * Ensures that tag-name-terminating characters close RCDATA and RAWTEXT elements. + * + * @dataProvider data_rcdata_and_rawtext_tag_name_terminators + * + * @param string $tag_name The RCDATA or RAWTEXT tag name. + * @param string $tag_name_terminator The tag-name-terminating character. + */ + public function test_rcdata_and_rawtext_end_tags_accept_tag_name_terminators( string $tag_name, string $tag_name_terminator ): void { + $end_tag_closer = '>' === $tag_name_terminator ? '' : '>'; + $processor = new WP_HTML_Tag_Processor( "<{$tag_name}>content" ); + + $this->assertTrue( $processor->next_token(), "Expected to find complete {$tag_name} tag." ); + $this->assertSame( strtoupper( $tag_name ), $processor->get_tag() ); + $this->assertSame( 'content', $processor->get_modifiable_text() ); + $this->assertTrue( $processor->next_tag( 'DIV' ), "Expected to find DIV after the {$tag_name} element." ); + } + + /** + * Provides every RCDATA and RAWTEXT tag with every tag-name-terminating character. + * + * @return Generator Test cases. + */ + public static function data_rcdata_and_rawtext_tag_name_terminators(): Generator { + foreach ( array( 'IFRAME', 'NOEMBED', 'NOFRAMES', 'STYLE', 'XMP', 'TEXTAREA', 'TITLE' ) as $tag_name ) { + foreach ( self::data_tag_name_terminators() as $terminator_name => $terminator_data ) { + yield "{$tag_name} + {$terminator_name}" => array( strtolower( $tag_name ), $terminator_data[0] ); + } + } + } + + /** + * Provides tag-name-terminating characters. + * + * @return Generator Test cases. + */ + public static function data_tag_name_terminators(): Generator { + yield 'SPACE' => array( ' ' ); + yield 'TAB' => array( "\t" ); + yield 'LINE FEED' => array( "\n" ); + yield 'FORM FEED' => array( "\f" ); + yield 'CARRIAGE RETURN' => array( "\r" ); + yield 'SOLIDUS' => array( '/' ); + yield 'GREATER-THAN SIGN' => array( '>' ); + } + /** * Invalid tag names are comments on tag closers. *