From b2b3ae18620bec646f24e00cfbb9c2650302423c Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 13 Aug 2024 13:36:33 -0700 Subject: [PATCH 1/3] 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. Follow-up to [58613]. Props dmsnell, westonruter. See #61545. --- src/wp-includes/html-api/class-wp-html-tag-processor.php | 8 +++++++- 1 file changed, 7 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; } From f93df18ff4fb5e570ae555a7b0efbc43d16c733e Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 13 Aug 2024 13:45:18 -0700 Subject: [PATCH 2/3] Add test verifying behavior. --- .../tests/html-api/wpHtmlTagProcessor.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index b9c6817988032..dfb2e8416499f 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -601,6 +601,24 @@ 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.' + ); + } + /** * @ticket 59209 * From a518f8671c545ff356e453e8e61c9c3c25daa215 Mon Sep 17 00:00:00 2001 From: Dennis Snell Date: Tue, 13 Aug 2024 14:19:15 -0700 Subject: [PATCH 3/3] Add negative test. Co-authored-by: Weston Ruter --- tests/phpunit/tests/html-api/wpHtmlTagProcessor.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index dfb2e8416499f..908e286a8fb21 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -617,6 +617,13 @@ public function test_next_tag_should_not_match_on_substrings_of_a_requested_tag( $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." + ); } /**