diff --git a/src/wp-includes/html-api/class-wp-html-decoder.php b/src/wp-includes/html-api/class-wp-html-decoder.php
index e4634f8fa23ed..6c375b8512946 100644
--- a/src/wp-includes/html-api/class-wp-html-decoder.php
+++ b/src/wp-includes/html-api/class-wp-html-decoder.php
@@ -361,7 +361,7 @@ public static function read_character_reference( $context, $text, $at = 0, &$mat
$name_length = 0;
$replacement = $html5_named_character_references->read_token( $text, $name_at, $name_length );
- if ( false === $replacement ) {
+ if ( null === $replacement ) {
return null;
}
diff --git a/tests/phpunit/tests/html-api/wpHtmlDecoder.php b/tests/phpunit/tests/html-api/wpHtmlDecoder.php
index 158115cdfbf06..abbee250e2454 100644
--- a/tests/phpunit/tests/html-api/wpHtmlDecoder.php
+++ b/tests/phpunit/tests/html-api/wpHtmlDecoder.php
@@ -110,6 +110,39 @@ static function ( int $errno, string $errstr ) use ( &$errors ) {
$this->assertSame( "&\x00b", $decoded, 'Should have decoded the text without changing it.' );
}
+ /**
+ * Ensures unmatched named character references leave the by-ref match length unchanged.
+ *
+ * @dataProvider data_unmatched_named_character_references
+ *
+ * @ticket 65372
+ *
+ * @param string $context Decoder context.
+ * @param string $raw_text_node Raw text containing an unmatched named character reference.
+ */
+ public function test_unmatched_named_character_reference_does_not_set_match_byte_length( $context, $raw_text_node ): void {
+ $match_byte_length = 'sentinel';
+ $this->assertNull(
+ WP_HTML_Decoder::read_character_reference( $context, $raw_text_node, 0, $match_byte_length ),
+ 'Should not have matched an unmatched named character reference.'
+ );
+ $this->assertSame( 'sentinel', $match_byte_length );
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array.
+ */
+ public static function data_unmatched_named_character_references(): array {
+ return array(
+ 'text invalid name' => array( 'data', '&bogus;' ),
+ 'text invalid short-name candidate' => array( 'data', '&Fv=q' ),
+ 'attribute invalid name' => array( 'attribute', '&bogus;' ),
+ 'attribute invalid short-name candidate' => array( 'attribute', '&Fv=q' ),
+ );
+ }
+
/**
* Ensures semicolonless legacy references decode before non-ASCII UTF-8 bytes in attributes.
*