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 94f6e798ff238..bd513d058cda7 100644
--- a/src/wp-includes/html-api/class-wp-html-decoder.php
+++ b/src/wp-includes/html-api/class-wp-html-decoder.php
@@ -179,19 +179,19 @@ public static function decode_attribute( $text, $at = 0, $length = null ) {
* @return string Decoded string.
*/
public static function decode( $context, $text, $at = 0, $length = null ) {
- $decoded = '';
- $end = isset( $length ) ? $at + $length : strlen( $text );
- $was_at = $at;
+ $decoded = '';
+ $end = isset( $length ) ? $at + $length : strlen( $text );
+ $started_at = $at;
+ $was_at = $at;
while ( $at < $end ) {
- $next_character_reference_at = strpos( $text, '&', $at );
- if ( false === $next_character_reference_at ) {
- break;
+ if ( '&' !== $text[ $at ] ) {
+ ++$at;
+ continue;
}
- $character_reference = self::read_character_reference( $context, $text, $next_character_reference_at, $skip_bytes );
+ $character_reference = self::read_character_reference( $context, $text, $at, $skip_bytes );
if ( isset( $character_reference ) ) {
- $at = $next_character_reference_at;
$decoded .= substr( $text, $was_at, $at - $was_at );
$decoded .= $character_reference;
$at += $skip_bytes;
@@ -202,8 +202,8 @@ public static function decode( $context, $text, $at = 0, $length = null ) {
++$at;
}
- if ( 0 === $was_at ) {
- return $text;
+ if ( $started_at === $was_at ) {
+ return substr( $text, $started_at, $length );
}
if ( $was_at < $end ) {
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 c4a5ffe6de7a8..090e22b2eac34 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
@@ -2494,8 +2494,9 @@ private function get_enqueued_attribute_value( $comparable_name ) {
* 2. Double-quoting starts one after the equals sign.
* 3. Double-quoting ends at the last character in the update.
*/
- $enqueued_value = substr( $enqueued_text, $equals_at + 2, -1 );
- return WP_HTML_Decoder::decode_attribute( $enqueued_value );
+ $start_at = $equals_at + 2;
+ $end_at = strlen( $enqueued_text ) - 1;
+ return WP_HTML_Decoder::decode_attribute( $enqueued_text, $start_at, $end_at - $start_at );
}
/**
@@ -2566,9 +2567,7 @@ public function get_attribute( $name ) {
return true;
}
- $raw_value = substr( $this->html, $attribute->value_starts_at, $attribute->value_length );
-
- return WP_HTML_Decoder::decode_attribute( $raw_value );
+ return WP_HTML_Decoder::decode_attribute( $this->html, $attribute->value_starts_at, $attribute->value_length );
}
/**
@@ -2841,8 +2840,6 @@ public function get_modifiable_text() {
return '';
}
- $text = substr( $this->html, $this->text_starts_at, $this->text_length );
-
// Comment data is not decoded.
if (
self::STATE_CDATA_NODE === $this->parser_state ||
@@ -2850,7 +2847,7 @@ public function get_modifiable_text() {
self::STATE_DOCTYPE === $this->parser_state ||
self::STATE_FUNKY_COMMENT === $this->parser_state
) {
- return $text;
+ return substr( $this->html, $this->text_starts_at, $this->text_length );
}
$tag_name = $this->get_tag();
@@ -2865,10 +2862,10 @@ public function get_modifiable_text() {
'STYLE' === $tag_name ||
'XMP' === $tag_name
) {
- return $text;
+ return substr( $this->html, $this->text_starts_at, $this->text_length );
}
- $decoded = WP_HTML_Decoder::decode_text_node( $text );
+ $decoded = WP_HTML_Decoder::decode_text_node( $this->html, $this->text_starts_at, $this->text_length );
/*
* TEXTAREA skips a leading newline, but this newline may appear not only as the