Commit 18128f8ba8 for wordpress.org
commit 18128f8ba82c9c4701a13da0b17099662ea8de35
Author: peterwilsoncc <peterwilsoncc@git.wordpress.org>
Date: Mon Sep 28 01:57:50 2026 +0000
Options, Meta APIs: Ensure meta cache is an array before use.
In `get_metadata_raw()` and `metadata_exists()` ensure that cached data is of a valid form (ie, an array) before use. This prevents PHP errors of a third party has set the cache directly using a non array value.
Each of these functions now treat invalid cache forms as a cache miss. Invalid cache entries are deleted in `update_meta_cache()` if they are not an array.
Props josephscott, jonsurrell, westonruter.
Fixes #66091.
Built from https://develop.svn.wordpress.org/trunk@63958
git-svn-id: http://core.svn.wordpress.org/trunk@63124 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/meta.php b/wp-includes/meta.php
index dd28b02721..6adcf389d5 100644
--- a/wp-includes/meta.php
+++ b/wp-includes/meta.php
@@ -632,6 +632,7 @@ function get_metadata( $meta_type, $object_id, $meta_key = '', $single = false )
* Retrieves raw metadata value for the specified object.
*
* @since 5.5.0
+ * @since 7.2.0 A cached value that is not an array is now treated as a cache miss.
*
* @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
* 'user', or any other object type with an associated meta table.
@@ -708,7 +709,8 @@ function get_metadata_raw( $meta_type, $object_id, $meta_key = '', $single = fal
$meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
- if ( ! $meta_cache ) {
+ // A cached value that is not an array is unusable, treat it as a cache miss.
+ if ( ! $meta_cache || ! is_array( $meta_cache ) ) {
$meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
$meta_cache = $meta_cache[ $object_id ] ?? null;
}
@@ -792,6 +794,7 @@ function get_metadata_default( $meta_type, $object_id, $meta_key, $single = fals
* Determines if a meta field with the given key exists for the given object ID.
*
* @since 3.3.0
+ * @since 7.2.0 A cached value that is not an array is now treated as a cache miss.
*
* @param string $meta_type Type of object metadata is for. Accepts 'blog', 'post', 'comment', 'term',
* 'user', or any other object type with an associated meta table.
@@ -817,9 +820,10 @@ function metadata_exists( $meta_type, $object_id, $meta_key ) {
$meta_cache = wp_cache_get( $object_id, $meta_type . '_meta' );
- if ( ! $meta_cache ) {
+ // A cached value that is not an array is unusable, treat it as a cache miss.
+ if ( ! $meta_cache || ! is_array( $meta_cache ) ) {
$meta_cache = update_meta_cache( $meta_type, array( $object_id ) );
- $meta_cache = $meta_cache[ $object_id ];
+ $meta_cache = $meta_cache[ $object_id ] ?? null;
}
if ( isset( $meta_cache[ $meta_key ] ) ) {
@@ -1165,6 +1169,7 @@ function delete_metadata_by_mid( $meta_type, $meta_id ) {
* Updates the metadata cache for the specified objects.
*
* @since 2.9.0
+ * @since 7.2.0 A cached value that is not an array is now treated as a cache miss.
*
* @global wpdb $wpdb WordPress database abstraction object.
*
@@ -1219,19 +1224,33 @@ function update_meta_cache( $meta_type, $object_ids ) {
return (bool) $check;
}
- $cache_group = $meta_type . '_meta';
- $non_cached_ids = array();
- $cache = array();
- $cache_values = wp_cache_get_multiple( $object_ids, $cache_group );
+ $cache_group = $meta_type . '_meta';
+ $non_cached_ids = array();
+ $invalid_cache_ids = array();
+ $cache = array();
+ $cache_values = wp_cache_get_multiple( $object_ids, $cache_group );
foreach ( $cache_values as $id => $cached_object ) {
if ( false === $cached_object ) {
$non_cached_ids[] = $id;
+ } elseif ( ! is_array( $cached_object ) ) {
+ // A cached value that is not an array is unusable, treat it as a cache miss.
+ $non_cached_ids[] = $id;
+ $invalid_cache_ids[] = $id;
} else {
$cache[ $id ] = $cached_object;
}
}
+ /*
+ * Remove unusable cached values so that the regenerated values can be added.
+ * A delete followed by an add is used instead of wp_cache_set_multiple()
+ * so that wp_suspend_cache_addition() is still respected.
+ */
+ if ( ! empty( $invalid_cache_ids ) ) {
+ wp_cache_delete_multiple( $invalid_cache_ids, $cache_group );
+ }
+
if ( empty( $non_cached_ids ) ) {
return $cache;
}
@@ -1268,6 +1287,7 @@ function update_meta_cache( $meta_type, $object_ids ) {
}
$data[ $id ] = $cache[ $id ];
}
+
wp_cache_add_multiple( $data, $cache_group );
return $cache;
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 3d03be3baa..293de607ce 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-63957';
+$wp_version = '7.2-alpha-63958';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.