From 2c8756be751b17b17198ee823c9f6a63f815cd20 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 3 Dec 2025 13:55:20 +0100 Subject: [PATCH 1/4] Add failing test for ticket 64340 --- .../tests/html-api/wpHtmlTagProcessor.php | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index b6ec3affb2788..41ed5aca825c6 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -3028,6 +3028,53 @@ public static function data_updating_attributes_in_malformed_html() { ); } + /** + * @ticket 64340 + */ + public function test_class_changes_produce_correct_html() { + $processor = new WP_HTML_Tag_Processor( '
' ); + $processor->next_tag(); + + $processor->add_class( '&' ); + $processor->get_updated_html(); + + $processor->add_class( '"' ); + $processor->get_updated_html(); + + $processor->add_class( 'OK' ); + $processor->get_updated_html(); + + $this->assertTrue( $processor->has_class( '&' ), 'Missing expected "&" class.' ); + $this->assertTrue( $processor->has_class( '"' ), 'Missing expected \'"\' class.' ); + $this->assertTrue( $processor->has_class( 'OK' ), 'Missing expected "OK" class.' ); + + $expected = '
'; + $this->assertEqualHTML( + $expected, + $processor->get_updated_html(), + '', + 'HTML was not correctly updated after adding classes.' + ); + + $processor->remove_class( '&' ); + $processor->get_updated_html(); + + $processor->remove_class( '"' ); + $processor->get_updated_html(); + + $this->assertFalse( $processor->has_class( '&' ) ); + $this->assertFalse( $processor->has_class( '"' ) ); + $this->assertTrue( $processor->has_class( 'OK' ) ); + + $expected = '
'; + $this->assertEqualHTML( + $expected, + $processor->get_updated_html(), + '', + 'HTML was not correctly updated after removing classes.' + ); + } + /** * @covers WP_HTML_Tag_Processor::next_tag */ From cf42da884fa37bdb900fe6cee2219ad97730c98a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 3 Dec 2025 14:01:01 +0100 Subject: [PATCH 2/4] Include correctly encoded HTML class name "&" initially --- tests/phpunit/tests/html-api/wpHtmlTagProcessor.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index 41ed5aca825c6..47f49b1d3a44a 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -3032,12 +3032,9 @@ public static function data_updating_attributes_in_malformed_html() { * @ticket 64340 */ public function test_class_changes_produce_correct_html() { - $processor = new WP_HTML_Tag_Processor( '
' ); + $processor = new WP_HTML_Tag_Processor( '
' ); $processor->next_tag(); - $processor->add_class( '&' ); - $processor->get_updated_html(); - $processor->add_class( '"' ); $processor->get_updated_html(); From 135f3dd5b41cda85a43fc48e2ff6ca0d7afc4930 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 3 Dec 2025 13:58:14 +0100 Subject: [PATCH 3/4] Add missing attribute decode when accessing raw class attribute HTML --- .../html-api/class-wp-html-tag-processor.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 3cdbd91480ca0..31c4bc8a10654 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 @@ -2342,10 +2342,12 @@ private function class_name_updates_to_attributes_updates(): void { } if ( false === $existing_class && isset( $this->attributes['class'] ) ) { - $existing_class = substr( - $this->html, - $this->attributes['class']->value_starts_at, - $this->attributes['class']->value_length + $existing_class = WP_HTML_Decoder::decode_attribute( + substr( + $this->html, + $this->attributes['class']->value_starts_at, + $this->attributes['class']->value_length + ) ); } From 99d7043cac8bed796935e10b479091115fe17554 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 3 Dec 2025 14:29:24 +0100 Subject: [PATCH 4/4] Update tests enforcing double-encoding --- tests/phpunit/tests/html-api/wpHtmlTagProcessor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index 47f49b1d3a44a..22ace3890f469 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -2887,11 +2887,11 @@ public static function data_updating_attributes_in_malformed_html() { ), 'HTML tag opening inside attribute value' => array( 'input' => '
This <is> a <strong is="true">thing.
test', - 'expected' => '
This <is> a <strong is="true">thing.
test', + 'expected' => '
This <is> a <strong is="true">thing.
test', ), 'HTML tag brackets in attribute values and data markup' => array( 'input' => '
This <is> a <strong is="true">thing.
test', - 'expected' => '
This <is> a <strong is="true">thing.
test', + 'expected' => '
This <is> a <strong is="true">thing.
test', ), 'Single and double quotes in attribute value' => array( 'input' => '

test',