Skip to content

Commit

Permalink
Fix: Prevent infinite loop in Tag Processor in certain truncated docu…
Browse files Browse the repository at this point in the history
…ments.

Previously the Tag Processor class has performed unchecked arithmetic on
the result of `strpos()` when looking to close out HTML comments and other
special sections (CDATA, doctype-declaration). This led to a situation
where by means of type-coercion we added an integer value to a `false`
returned by the string function, setting the cursor in the tag processor
to a low index in the document, and creating an infinite loop condition.

In this patch we're checking the results of calling `strpos()` in those
places to avoid the type error and abort from the processor if we fail
to find the end of those associated document sections.
  • Loading branch information
dmsnell committed Nov 4, 2022
1 parent 984e9d8 commit f921a4e
Showing 1 changed file with 36 additions and 9 deletions.
45 changes: 36 additions & 9 deletions lib/experimental/html/class-wp-html-tag-processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ private function skip_rcdata( $tag_name ) {

$at = $this->parsed_bytes;

while ( true ) {
while ( false !== $at && $at < $doc_length ) {
$at = strpos( $this->html, '</', $at );

// If we have no possible tag closer then fail.
Expand Down Expand Up @@ -494,6 +494,8 @@ private function skip_rcdata( $tag_name ) {
return;
}
}

return false;
}

/**
Expand All @@ -507,7 +509,7 @@ private function skip_script_data() {
$doc_length = strlen( $html );
$at = $this->parsed_bytes;

while ( $at < $doc_length ) {
while ( false !== $at && $at < $doc_length ) {
$at += strcspn( $html, '-<', $at );

/*
Expand Down Expand Up @@ -613,6 +615,8 @@ private function skip_script_data() {

++$at;
}

return false;
}

/**
Expand All @@ -623,10 +627,11 @@ private function skip_script_data() {
private function parse_next_tag() {
$this->after_tag();

$html = $this->html;
$at = $this->parsed_bytes;
$html = $this->html;
$doc_length = strlen( $html );
$at = $this->parsed_bytes;

while ( true ) {
while ( false !== $at && $at < $doc_length ) {
$at = strpos( $html, '<', $at );
if ( false === $at ) {
return false;
Expand Down Expand Up @@ -663,7 +668,12 @@ private function parse_next_tag() {
'-' === $html[ $at + 2 ] &&
'-' === $html[ $at + 3 ]
) {
$at = strpos( $html, '-->', $at + 4 ) + 3;
$closer_at = strpos( $html, '-->', $at + 4 );
if ( false === $closer_at ) {
return false;
}

$at = $closer_at + 3;
continue;
}

Expand All @@ -680,7 +690,12 @@ private function parse_next_tag() {
'A' === $html[ $at + 7 ] &&
'[' === $html[ $at + 8 ]
) {
$at = strpos( $html, ']]>', $at + 9 ) + 3;
$closer_at = strpos( $html, ']]>', $at + 9 );
if ( false === $closer_at ) {
return false;
}

$at = $closer_at + 3;
continue;
}

Expand All @@ -699,7 +714,12 @@ private function parse_next_tag() {
'P' === strtoupper( $html[ $at + 7 ] ) &&
'E' === strtoupper( $html[ $at + 8 ] )
) {
$at = strpos( $html, '>', $at + 9 ) + 1;
$closer_at = strpos( $html, '>', $at + 9 );
if ( false === $closer_at ) {
return false;
}

$at = $closer_at + 1;
continue;
}

Expand All @@ -716,12 +736,19 @@ private function parse_next_tag() {
* https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
*/
if ( '?' === $html[ $at + 1 ] ) {
$at = strpos( $html, '>', $at + 2 ) + 1;
$closer_at = strpos( $html, '>', $at + 2 );
if ( false === $closer_at ) {
return false;
}

$at = $closer_at + 1;
continue;
}

++$at;
}

return false;
}

/**
Expand Down

0 comments on commit f921a4e

Please sign in to comment.