From a10ab726893697e80750089e718bff5c202fb1bf Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Wed, 20 Aug 2025 16:08:38 -0500 Subject: [PATCH 1/6] Handle non-string values in WP_HTML_Tag_Processor --- .../html-api/class-wp-html-tag-processor.php | 9 +++++++++ .../tests/html-api/wpHtmlTagProcessor.php | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) 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 b2c9db57c169a..d761e5c985f8b 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 @@ -830,10 +830,19 @@ class WP_HTML_Tag_Processor { * Constructor. * * @since 6.2.0 + * @since 6.9.0 Executes doing_it_wrong() when the HTML parameter is not a string. * * @param string $html HTML to process. */ public function __construct( $html ) { + if ( ! is_string( $html ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The HTML parameter must be a string.' ), + '6.9.0' + ); + $html = ''; + } $this->html = $html; } diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index 6a06109eafe13..5377f06a23a32 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -72,6 +72,25 @@ public function test_has_self_closing_flag_matches_input_html( $html, $flag_is_s } } + /** + * @ticket 6.9.0 + * + * @covers WP_HTML_Tag_Processor::__construct + */ + public function test_constructor_validates_html_parameter() { + // Expect the _doing_it_wrong call. + $this->setExpectedIncorrectUsage( 'WP_HTML_Tag_Processor::__construct' ); + + // Test that passing null triggers _doing_it_wrong and sets HTML to empty string. + $processor = new WP_HTML_Tag_Processor( null ); + + // Verify that the HTML was set to an empty string. + $this->assertSame( '', $processor->get_updated_html(), 'HTML should be set to empty string when null is passed' ); + + // Verify that next_token() works without errors (indicating the processor is in a valid state). + $this->assertFalse( $processor->next_token(), 'next_token() should work without errors when HTML is empty string' ); + } + /** * Data provider. HTML tags which might have a self-closing flag, and an indicator if they do. * From 154929118b405a98a0a3a530092140f506a360d4 Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Fri, 22 Aug 2025 12:31:51 -0500 Subject: [PATCH 2/6] Trac ticket number Co-authored-by: Jon Surrell --- tests/phpunit/tests/html-api/wpHtmlTagProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index 5377f06a23a32..b0cdea034d2cb 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -73,7 +73,7 @@ public function test_has_self_closing_flag_matches_input_html( $html, $flag_is_s } /** - * @ticket 6.9.0 + * @ticket 63854 * * @covers WP_HTML_Tag_Processor::__construct */ From e366ee33f6d281d8e0d31a747814dfabd6dc1948 Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Fri, 22 Aug 2025 12:33:04 -0500 Subject: [PATCH 3/6] Remove the since annotation --- src/wp-includes/html-api/class-wp-html-tag-processor.php | 1 - 1 file changed, 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 d761e5c985f8b..d3c09ff4fbc2f 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 @@ -830,7 +830,6 @@ class WP_HTML_Tag_Processor { * Constructor. * * @since 6.2.0 - * @since 6.9.0 Executes doing_it_wrong() when the HTML parameter is not a string. * * @param string $html HTML to process. */ From 884dc042d1bf7152f7fd96723923b41c87f79c44 Mon Sep 17 00:00:00 2001 From: Brandon Kraft Date: Tue, 30 Sep 2025 13:13:33 -0500 Subject: [PATCH 4/6] Defensive coding for non-strings in ::create_fragment and ::create_full_parser --- .../html-api/class-wp-html-processor.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) 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 660e43ba659b4..336c83949c0dc 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -297,6 +297,15 @@ public static function create_fragment( $html, $context = '', $encoding = return null; } + if ( ! is_string( $html ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The HTML parameter must be a string.' ), + '6.9.0' + ); + return null; + } + $context_processor = static::create_full_parser( "{$context}", $encoding ); if ( null === $context_processor ) { return null; @@ -339,6 +348,14 @@ public static function create_full_parser( $html, $known_definite_encoding = 'UT if ( 'UTF-8' !== $known_definite_encoding ) { return null; } + if ( ! is_string( $html ) ) { + _doing_it_wrong( + __METHOD__, + __( 'The HTML parameter must be a string.' ), + '6.9.0' + ); + return null; + } $processor = new static( $html, self::CONSTRUCTOR_UNLOCK_CODE ); $processor->state->encoding = $known_definite_encoding; From 8d2adae0887943a3ef49c3b5d5ba4c8f7cd00def Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 1 Oct 2025 08:59:07 +0200 Subject: [PATCH 5/6] Add HTML processor doing it wrong tests --- .../tests/html-api/wpHtmlProcessor.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/phpunit/tests/html-api/wpHtmlProcessor.php b/tests/phpunit/tests/html-api/wpHtmlProcessor.php index 1ca60e691f03e..13e0728ca912a 100644 --- a/tests/phpunit/tests/html-api/wpHtmlProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlProcessor.php @@ -36,6 +36,28 @@ public function test_warns_that_the_static_creator_methods_should_be_called_inst new WP_HTML_Processor( '

Light roast.

' ); } + /** + * @ticket 63854 + * + * @covers ::create_fragment + * @expectedIncorrectUsage WP_HTML_Processor::create_fragment + */ + public function test_create_fragment_validates_html_parameter() { + $processor = WP_HTML_Processor::create_fragment( null ); + $this->assertNull( $processor ); + } + + /** + * @ticket 63854 + * + * @covers ::create_full_parser + * @expectedIncorrectUsage WP_HTML_Processor::create_full_parser + */ + public function test_create_full_parser_validates_html_parameter() { + $processor = WP_HTML_Processor::create_full_parser( null ); + $this->assertNull( $processor ); + } + /** * 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 From d27eb395f420f7dcbcd1e8483541cb78eb8d3221 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Wed, 1 Oct 2025 09:00:42 +0200 Subject: [PATCH 6/6] Use expectedIncorrectUsage test annotation over method This makes it easier to run the HTML API tests in isolation without the entire phpunit configuration. --- tests/phpunit/tests/html-api/wpHtmlTagProcessor.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php index b0cdea034d2cb..53bba243a99a0 100644 --- a/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php +++ b/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php @@ -76,11 +76,9 @@ public function test_has_self_closing_flag_matches_input_html( $html, $flag_is_s * @ticket 63854 * * @covers WP_HTML_Tag_Processor::__construct + * @expectedIncorrectUsage WP_HTML_Tag_Processor::__construct */ public function test_constructor_validates_html_parameter() { - // Expect the _doing_it_wrong call. - $this->setExpectedIncorrectUsage( 'WP_HTML_Tag_Processor::__construct' ); - // Test that passing null triggers _doing_it_wrong and sets HTML to empty string. $processor = new WP_HTML_Tag_Processor( null );