mirror of
https://github.com/WordPress/WordPress.git
synced 2026-06-19 07:37:07 +00:00
Editor: Guard against non-string className in wp_render_elements_class_name() block render filter callback.
The `wp_render_elements_class_name()` function reads the `className` block attribute and passes it straight to `preg_match()`. While `className` is expected to be a string, malformed or corrupted stored block data can hold another type, such as an array, which triggers a fatal `TypeError` on PHP 8+. Guard against this by returning the block content unchanged when `className` is not a string. While here, align the implementation with `wp_render_custom_css_class_name()` from r62359: replace the regular expression with a `str_contains()` short-circuit followed by an HTML-spec-compliant `strtok()` walk over the class tokens. This also corrects a latent matching bug: the previous `\bwp-elements-\S+\b` pattern treated the hyphen as a word boundary, so a class such as `my-wp-elements-foo` was erroneously matched. Tokenizing the attribute first ensures only a standalone `wp-elements-*` class is applied. Add regression tests for the non-string and substring-prefix cases, and resolve PHPStan errors at rule level 10 (`missingType.iterableValue`, `offsetAccess.nonOffsetAccessible`, `argument.type`) by adding an array shape to the `@phpstan-param` tag. Developed in https://github.com/WordPress/wordpress-develop/pull/12028 and https://github.com/WordPress/gutenberg/pull/78841. Follow-up to r58074, r62359. Props aaronrobertshaw, andrewserong, mukesh27, westonruter. Fixes #65379. Built from https://develop.svn.wordpress.org/trunk@62475 git-svn-id: http://core.svn.wordpress.org/trunk@61756 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
@@ -98,32 +98,31 @@ function wp_enqueue_block_custom_css() {
|
||||
* } $block
|
||||
*/
|
||||
function wp_render_custom_css_class_name( $block_content, $block ) {
|
||||
$class_name_attr = $block['attrs']['className'] ?? null;
|
||||
|
||||
if ( ! is_string( $class_name_attr ) || ! str_contains( $class_name_attr, 'wp-custom-css-' ) ) {
|
||||
$class_name_attr = $block['attrs']['className'] ?? null;
|
||||
$class_name_prefix = 'wp-custom-css-';
|
||||
if ( ! is_string( $class_name_attr ) || ! str_contains( $class_name_attr, $class_name_prefix ) ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
// Parse out the 'wp-custom-css-*' class name added by wp_render_custom_css_support_styles().
|
||||
$custom_class_name = null;
|
||||
$token_delimiter = " \t\f\r\n";
|
||||
$class_token = strtok( $class_name_attr, $token_delimiter );
|
||||
$matched_class_name = null;
|
||||
$token_delimiter = " \t\f\r\n";
|
||||
$class_token = strtok( $class_name_attr, $token_delimiter );
|
||||
while ( false !== $class_token ) {
|
||||
if ( str_starts_with( $class_token, 'wp-custom-css-' ) ) {
|
||||
$custom_class_name = $class_token;
|
||||
if ( str_starts_with( $class_token, $class_name_prefix ) ) {
|
||||
$matched_class_name = $class_token;
|
||||
break;
|
||||
}
|
||||
$class_token = strtok( $token_delimiter );
|
||||
}
|
||||
if ( null === $custom_class_name ) {
|
||||
if ( null === $matched_class_name ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
$tags = new WP_HTML_Tag_Processor( $block_content );
|
||||
|
||||
if ( $tags->next_tag() ) {
|
||||
$tags->add_class( 'has-custom-css' );
|
||||
$tags->add_class( $custom_class_name );
|
||||
$tags->add_class( $matched_class_name );
|
||||
}
|
||||
|
||||
return $tags->get_updated_html();
|
||||
|
||||
@@ -237,22 +237,43 @@ function wp_render_elements_support_styles( $parsed_block ) {
|
||||
* @see wp_render_elements_support_styles
|
||||
* @since 6.6.0
|
||||
*
|
||||
* @param string $block_content Rendered block content.
|
||||
* @param array $block Block object.
|
||||
* @return string Filtered block content.
|
||||
* @param string $block_content Rendered block content.
|
||||
* @param array $block Block object.
|
||||
* @return string Filtered block content.
|
||||
*
|
||||
* @phpstan-param array{
|
||||
* attrs: array{
|
||||
* className?: string,
|
||||
* ...
|
||||
* },
|
||||
* ...
|
||||
* } $block
|
||||
*/
|
||||
function wp_render_elements_class_name( $block_content, $block ) {
|
||||
$class_string = $block['attrs']['className'] ?? '';
|
||||
preg_match( '/\bwp-elements-\S+\b/', $class_string, $matches );
|
||||
$class_name_attr = $block['attrs']['className'] ?? null;
|
||||
$class_name_prefix = 'wp-elements-';
|
||||
if ( ! is_string( $class_name_attr ) || ! str_contains( $class_name_attr, $class_name_prefix ) ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
if ( empty( $matches ) ) {
|
||||
// Parse out the 'wp-elements-*' class name.
|
||||
$matched_class_name = null;
|
||||
$token_delimiter = " \t\f\r\n";
|
||||
$class_token = strtok( $class_name_attr, $token_delimiter );
|
||||
while ( false !== $class_token ) {
|
||||
if ( str_starts_with( $class_token, $class_name_prefix ) ) {
|
||||
$matched_class_name = $class_token;
|
||||
break;
|
||||
}
|
||||
$class_token = strtok( $token_delimiter );
|
||||
}
|
||||
if ( null === $matched_class_name ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
$tags = new WP_HTML_Tag_Processor( $block_content );
|
||||
|
||||
if ( $tags->next_tag() ) {
|
||||
$tags->add_class( $matches[0] );
|
||||
$tags->add_class( $matched_class_name );
|
||||
}
|
||||
|
||||
return $tags->get_updated_html();
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
* @global string $wp_version
|
||||
*/
|
||||
$wp_version = '7.1-alpha-62474';
|
||||
$wp_version = '7.1-alpha-62475';
|
||||
|
||||
/**
|
||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||
|
||||
Reference in New Issue
Block a user