diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index 6e1723494c2e9..b5a20dbd82cdc 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -432,6 +432,11 @@ public function next_tag( $query = null ) { * @return bool Whether a tag was matched. */ public function step( $node_to_process = self::PROCESS_NEXT_NODE ) { + // Refuse to proceed if there was a previous error. + if ( null !== $this->last_error ) { + return false; + } + if ( self::PROCESS_NEXT_NODE === $node_to_process ) { $top_node = $this->state->stack_of_open_elements->current_node(); if ( $top_node && self::is_void( $top_node->node_name ) ) { @@ -744,6 +749,10 @@ private function bookmark_tag() { * @return string|null Name of currently matched tag in input HTML, or `null` if none found. */ public function get_tag() { + if ( null !== $this->last_error ) { + return null; + } + $tag_name = parent::get_tag(); switch ( $tag_name ) { diff --git a/tests/phpunit/tests/html-api/wpHtmlProcessor.php b/tests/phpunit/tests/html-api/wpHtmlProcessor.php index 6a666c19cf27c..d6b818dd44c34 100644 --- a/tests/phpunit/tests/html-api/wpHtmlProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlProcessor.php @@ -42,6 +42,40 @@ public function test_warns_that_the_static_creator_methods_should_be_called_inst ); } + /** + * Once stepping to the end of the document, WP_HTML_Processor::get_tag + * should no longer report a tag. It should report `null` because there + * is no tag matched or open. + * + * @ticket 59167 + * + * @covers WP_HTML_Processor::get_tag + */ + public function test_get_tag_is_null_once_document_is_finished() { + $p = WP_HTML_Processor::createFragment( '
Test
' ); + $p->next_tag(); + $this->assertSame( 'DIV', $p->get_tag() ); + + $this->assertFalse( $p->next_tag() ); + $this->assertNull( $p->get_tag() ); + } + + /** + * Ensures that if the HTML Processor encounters inputs that it can't properly handle, + * that it stops processing the rest of the document. This prevents data corruption. + * + * @ticket 59167 + * + * @covers WP_HTML_Processor::next_tag + */ + public function test_stops_processing_after_unsupported_elements() { + $p = WP_HTML_Processor::createFragment( '

' ); + $p->next_tag( 'P' ); + $this->assertFalse( $p->next_tag(), 'Stepped into a tag after encountering X-NOT-SUPPORTED element when it should have aborted.' ); + $this->assertNull( $p->get_tag(), "Should have aborted processing, but still reported tag {$p->get_tag()} after properly failing to step into tag." ); + $this->assertFalse( $p->next_tag( 'P' ), 'Stepped into normal P element after X-NOT-SUPPORTED element when it should have aborted.' ); + } + /** * Ensures that the HTML Processor maintains its internal state through seek calls. *