Commit 467a6b3200 for wordpress.org
commit 467a6b3200e942fbe5c8160845fc333c7a00b5ce
Author: ramonopoly <ramonopoly@git.wordpress.org>
Date: Mon Oct 12 08:19:51 2026 +0000
Editor: Ignore theme.json values of unexpected types
This commit prevents `WP_Theme_JSON` from throwing fatal TypeErrors when theme.json or global styles data contains values of the wrong type.
Those values could be user- or AI-generated.
The checks in this commit cover spacing scale arrays, block variation selectors, and custom block CSS processing.
The motivation arose from a real-life PHP fatal where `WP_Theme_JSON::process_blocks_custom_css` attempted to explode a non-string.
Developed in: https://github.com/WordPress/wordpress-develop/pull/14190
Props ramonopoly, aaronrobertshaw, andrewserong.
Fixes #66286.
Built from https://develop.svn.wordpress.org/trunk@64309
git-svn-id: http://core.svn.wordpress.org/trunk@63459 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/class-wp-theme-json.php b/wp-includes/class-wp-theme-json.php
index c17f2b1b07..2f80a256b8 100644
--- a/wp-includes/class-wp-theme-json.php
+++ b/wp-includes/class-wp-theme-json.php
@@ -1140,7 +1140,7 @@ class WP_Theme_JSON {
// In addition to presets, spacingScale (which generates presets) is also keyed by origin.
$scale_path = array( 'settings', 'spacing', 'spacingScale' );
$spacing_scale = _wp_array_get( $this->theme_json, $scale_path, null );
- if ( null !== $spacing_scale ) {
+ if ( is_array( $spacing_scale ) ) {
// If the spacingScale is not already keyed by origin.
if ( empty( array_intersect( array_keys( $spacing_scale ), static::VALID_ORIGINS ) ) ) {
_wp_array_set( $this->theme_json, $scale_path, array( $origin => $spacing_scale ) );
@@ -1214,7 +1214,10 @@ class WP_Theme_JSON {
foreach ( $registered_variations as $variation_name ) {
$block_level_data = $new_theme_json['styles']['blocks'][ $block_type ]['variations'][ $variation_name ] ?? array();
$top_level_data = $variations[ $variation_name ] ?? array();
- $merged_data = array_replace_recursive( $top_level_data, $block_level_data );
+ if ( ! is_array( $block_level_data ) || ! is_array( $top_level_data ) ) {
+ continue;
+ }
+ $merged_data = array_replace_recursive( $top_level_data, $block_level_data );
if ( ! empty( $merged_data ) ) {
_wp_array_set( $new_theme_json, array( 'styles', 'blocks', $block_type, 'variations', $variation_name ), $merged_data );
}
@@ -1493,7 +1496,7 @@ class WP_Theme_JSON {
if ( ! empty( $input['blockTypes'] ) && is_array( $input['blockTypes'] ) ) {
$variation_pseudo_selectors = array();
foreach ( $input['blockTypes'] as $variation_block_type ) {
- if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $variation_block_type ] ) ) {
+ if ( is_string( $variation_block_type ) && isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $variation_block_type ] ) ) {
$variation_pseudo_selectors = array_merge(
$variation_pseudo_selectors,
static::VALID_BLOCK_PSEUDO_SELECTORS[ $variation_block_type ]
@@ -2101,7 +2104,10 @@ class WP_Theme_JSON {
// Load the custom CSS last so it has the highest specificity.
if ( in_array( 'custom-css', $types, true ) ) {
// Add the global styles root CSS.
- $stylesheet .= _wp_array_get( $this->theme_json, array( 'styles', 'css' ) );
+ $root_css = $this->theme_json['styles']['css'] ?? '';
+ if ( is_string( $root_css ) ) {
+ $stylesheet .= $root_css;
+ }
}
return $stylesheet;
@@ -2121,7 +2127,7 @@ class WP_Theme_JSON {
public static function process_blocks_custom_css( $css, $selector ) {
$processed_css = '';
- if ( empty( $css ) ) {
+ if ( empty( $css ) || ! is_string( $css ) ) {
return $processed_css;
}
@@ -3241,7 +3247,7 @@ class WP_Theme_JSON {
* In the case of backgroundImage, if both a ref and a URL are present in the value,
* the URL takes precedence and the ref is ignored.
*/
- if ( is_array( $value ) && isset( $value['ref'] ) ) {
+ if ( is_array( $value ) && isset( $value['ref'] ) && is_string( $value['ref'] ) ) {
$value_path = explode( '.', $value['ref'] );
$ref_value = _wp_array_get( $theme_json, $value_path );
// Background Image refs can refer to a string or an array containing a URL string.
@@ -4431,11 +4437,13 @@ class WP_Theme_JSON {
$scale_path = array( 'settings', 'spacing', 'spacingScale', $origin );
// Apply the base spacing scale to the current layer.
- $base_spacing_scale = _wp_array_get( $this->theme_json, $scale_path, array() );
- $flattened_spacing_scale = array_replace( $flattened_spacing_scale, $base_spacing_scale );
+ $base_spacing_scale = _wp_array_get( $this->theme_json, $scale_path, array() );
+ if ( is_array( $base_spacing_scale ) ) {
+ $flattened_spacing_scale = array_replace( $flattened_spacing_scale, $base_spacing_scale );
+ }
$spacing_scale = _wp_array_get( $incoming_data, $scale_path, null );
- if ( ! isset( $spacing_scale ) ) {
+ if ( ! is_array( $spacing_scale ) ) {
continue;
}
@@ -5569,6 +5577,7 @@ class WP_Theme_JSON {
! isset( $spacing_scale['mediumStep'] ) ||
! is_numeric( $spacing_scale['mediumStep'] ) ||
! isset( $spacing_scale['unit'] ) ||
+ ! is_string( $spacing_scale['unit'] ) ||
! isset( $spacing_scale['operator'] ) ||
( '+' !== $spacing_scale['operator'] && '*' !== $spacing_scale['operator'] ) ||
! isset( $spacing_scale['increment'] ) ||
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 1b34d7e5fd..52d32668f5 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-64308';
+$wp_version = '7.2-alpha-64309';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.