From c20224beaec66dd302616391df1890eba2c697f6 Mon Sep 17 00:00:00 2001 From: dmsnell Date: Tue, 13 Aug 2024 22:12:01 +0000 Subject: [PATCH] HTML API: Only stop on full matches for requested tag name. An optimization pass on the HTML API left a bug in the `matches()` method, whereby it would falsely detect a tag name match if the found tag were a lexical subset of the requested tag. This occurred because of the use of `substr_compare()` without checking that the outer lengths matched. This patch resolves the bug by adding the length check. Developed in https://github.com/wordpress/wordpress-develop/pull/7189 Discussed in https://core.trac.wordpress.org/ticket/61545 Follow-up to [58613]. Props dmsnell, westonruter. See #61545. git-svn-id: https://develop.svn.wordpress.org/trunk@58893 602fd350-edb4-49c9-b593-d223f7449a82 --- .../html-api/class-wp-html-tag-processor.php | 8 +++++- .../tests/html-api/wpHtmlTagProcessor.php | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) 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 95216b08a1988..11a0daa4b26f4 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 @@ -4009,7 +4009,13 @@ private function matches(): bool { } // Does the tag name match the requested tag name in a case-insensitive manner? - if ( isset( $this->sought_tag_name ) && 0 !== substr_compare( $this->html, $this->sought_tag_name, $this->tag_name_starts_at, $this->tag_name_length, true ) ) { + if ( + isset( $this->sought_tag_name ) && + ( + strlen( $this->sought_tag_name ) !== $this->tag_name_length || + 0 !== substr_compare( $this->html, $this->sought_tag_name, $this->tag_name_starts_at, $this->tag_name_length, true ) + ) + ) { return false; } diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index b9c6817988032..908e286a8fb21 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -601,6 +601,31 @@ public function test_next_tag_should_return_false_for_a_non_existing_tag() { $this->assertFalse( $processor->next_tag( 'p' ), 'Querying a non-existing tag did not return false' ); } + /** + * @ticket 61545 + */ + public function test_next_tag_should_not_match_on_substrings_of_a_requested_tag() { + $processor = new WP_HTML_Tag_Processor( '

' ); + + $this->assertTrue( + $processor->next_tag( 'PICTURE' ), + 'Failed to find a tag when requested: check test setup.' + ); + + $this->assertSame( + 'PICTURE', + $processor->get_tag(), + 'Should have skipped past substring tag matches, directly finding the PICTURE element.' + ); + + $processor = new WP_HTML_Tag_Processor( '

' ); + + $this->assertFalse( + $processor->next_tag( 'PICTURE' ), + "Should not have found any PICTURE element, but found '{$processor->get_token_name()}' instead." + ); + } + /** * @ticket 59209 *