From 146775070985b4a26def7eef563e97bd1e741228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Greg=20Zi=C3=83=C2=B3=C3=85=E2=80=9Akowski?= Date: Tue, 10 Dec 2024 09:11:35 +0000 Subject: [PATCH] HTML API: Prevent bookmarks from being set on virtual tokens Fixes the issue when an HTML_Processor bookmark was set at a virtual token (a node in the resulting document that does not correspond to an HTML token present in the input string), seek behavior was unreliable. Props jonsurrell, gziolo. Fixes #62521. git-svn-id: https://develop.svn.wordpress.org/trunk@59502 602fd350-edb4-49c9-b593-d223f7449a82 --- .../html-api/class-wp-html-processor.php | 17 ++++++++++++++++- .../tests/html-api/wpHtmlProcessor-bookmark.php | 13 +++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) 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 7b156d8a605fa..8d2a476769efe 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -303,7 +303,9 @@ public static function create_fragment( $html, $context = '', $encoding = } while ( $context_processor->next_tag() ) { - $context_processor->set_bookmark( 'final_node' ); + if ( ! $context_processor->is_virtual() ) { + $context_processor->set_bookmark( 'final_node' ); + } } if ( @@ -5673,12 +5675,25 @@ public function seek( $bookmark_name ): bool { * reaching for it, as inappropriate use could lead to broken * HTML structure or unwanted processing overhead. * + * Bookmarks cannot be set on tokens that do no appear in the original + * HTML text. For example, the HTML `
` stops at tags `TABLE`, + * `TBODY`, `TR`, and `TD`. The `TBODY` and `TR` tags do not appear in + * the original HTML and cannot be used as bookmarks. + * * @since 6.4.0 * * @param string $bookmark_name Identifies this particular bookmark. * @return bool Whether the bookmark was successfully created. */ public function set_bookmark( $bookmark_name ): bool { + if ( $this->is_virtual() ) { + _doing_it_wrong( + __METHOD__, + __( 'Cannot set bookmarks on tokens that do no appear in the original HTML text.' ), + '6.8.0' + ); + return false; + } return parent::set_bookmark( "_{$bookmark_name}" ); } diff --git a/tests/phpunit/tests/html-api/wpHtmlProcessor-bookmark.php b/tests/phpunit/tests/html-api/wpHtmlProcessor-bookmark.php index 91cc17898f77d..094fea367878a 100644 --- a/tests/phpunit/tests/html-api/wpHtmlProcessor-bookmark.php +++ b/tests/phpunit/tests/html-api/wpHtmlProcessor-bookmark.php @@ -157,4 +157,17 @@ public static function data_processor_constructors(): array { 'Fragment parser' => array( array( WP_HTML_Processor::class, 'create_fragment' ) ), ); } + + /** + * @ticket 62521 + * + * @expectedIncorrectUsage WP_HTML_Processor::set_bookmark + */ + public function test_bookmarks_not_allowed_on_virtual_nodes() { + $processor = WP_HTML_Processor::create_full_parser( 'text' ); + $this->assertTrue( $processor->next_tag( 'BODY' ) ); + $this->assertFalse( $processor->set_bookmark( 'mark' ) ); + $this->assertTrue( $processor->next_token() ); + $this->assertTrue( $processor->set_bookmark( 'mark' ) ); + } }