Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/wp-includes/class-wp-block-processor.php
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,11 @@ public function next_token(): bool {
$this->open_blocks_at[] = $after_prev_delimiter;
$this->open_blocks_length[] = 0;
$this->was_void = true;

if ( $backup > 0 ) {
$this->last_error = self::INCOMPLETE_INPUT;
}

return true;
}

Expand Down
60 changes: 60 additions & 0 deletions tests/phpunit/tests/block-processor/wpBlockProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,66 @@ public static function data_incomplete_html_comments_that_are_not_delimiters() {
);
}

/**
* Verifies that trailing bytes which could start a block comment delimiter
* are not reported as a delimiter.
*
* @ticket 66138
*
* @dataProvider data_documents_ending_in_a_partial_delimiter
*
* @covers ::next_token()
*
* @param string $html Input document.
* @param string[] $block_types Printable block type of every delimiter in the document, in order.
* @param string|null $last_error Expected error after scanning the entire document.
*/
public function test_reports_no_delimiter_for_partial_delimiter_at_end_of_document( $html, $block_types, $last_error ): void {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public function test_reports_no_delimiter_for_partial_delimiter_at_end_of_document( $html, $block_types, $last_error ): void {
public function test_reports_no_delimiter_for_partial_delimiter_at_end_of_document( string $html, array $block_types, ?string $last_error ): void {

$processor = new WP_Block_Processor( $html );

$found = array();
while ( $processor->next_delimiter() ) {
$found[] = $processor->get_printable_block_type();
}

$this->assertSame(
$block_types,
$found,
'Should have found only the delimiters which are in the document.'
);

$this->assertSame(
$last_error,
$processor->get_last_error(),
'Should have reported the expected error after reaching the end of the document.'
);
}

/**
* Data provider.
*
* @return array<string, array{0: string, 1: string[], 2: string|null}>
*/
public static function data_documents_ending_in_a_partial_delimiter(): array {
return array(
// Documents ending in a partial delimiter with no earlier delimiter.
'Ends in <' => array( 'text<', array(), WP_Block_Processor::INCOMPLETE_INPUT ),
'Ends in <!' => array( 'text<!', array(), WP_Block_Processor::INCOMPLETE_INPUT ),
'Ends in <!-' => array( 'text<!-', array(), WP_Block_Processor::INCOMPLETE_INPUT ),

// Documents ending in a partial delimiter after an earlier delimiter.
'Opener, then ends in <' => array( '<!-- wp:a -->text<', array( 'core/a' ), WP_Block_Processor::INCOMPLETE_INPUT ),
'Opener, then ends in <!' => array( '<!-- wp:a -->text<!', array( 'core/a' ), WP_Block_Processor::INCOMPLETE_INPUT ),
'Opener, then ends in <!-' => array( '<!-- wp:a -->text<!-', array( 'core/a' ), WP_Block_Processor::INCOMPLETE_INPUT ),
'Void, then ends in <!-' => array( '<!-- wp:a /-->text<!-', array( 'core/a' ), WP_Block_Processor::INCOMPLETE_INPUT ),
'Closer, then ends in <' => array( '<!-- /wp:a -->text<', array( 'core/a' ), WP_Block_Processor::INCOMPLETE_INPUT ),

// Documents which do not end in a partial delimiter.
'Contains < but ends in text' => array( 'a<b', array(), null ),
'Opener and trailing text' => array( '<!-- wp:a -->text', array( 'core/a' ), null ),
);
}

/**
* Verifies that block delimiters are matched even with malformed
* JSON attributes as long as they start and end with curly brackets.
Expand Down
Loading