Conversation
|
Just to summarize our slack conversation:
We agreed on taking no further action at the moment in 2.x but will refactor the method in a future 3.0 release in order to maintain compatibility. |
| return $data; | ||
|
|
||
| // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize | ||
| return serialize( $data ); |
There was a problem hiding this comment.
Always serialize, except if it already was serialized? @naxvog thoughts?
There was a problem hiding this comment.
Does Redis currently contain double serialized data? If so, what were the use cases?
There was a problem hiding this comment.
<?php
class Naxvog_Test {
private $creation_time;
private $serialization_time;
public $some_prop;
private $some_secret_prop;
public function __construct() {
$this->creation_time = time();
$this->some_secret_prop = 'baz';
$this->some_prop = 'bar';
}
public function __serialize() {
return [
'serialization_time' => time(),
'creation_time' => $this->creation_time,
];
}
public function __unserialize( $data ) {
$this->serialization_time = $data['serialization_time'];
$this->creation_time = $data['creation_time'];
}
}
add_action( 'init', function() {
$a = new Naxvog_Test();
$s = serialize( $a );
#var_dump( $a, $s );
#var_dump( unserialize( $s ) );
if ( isset( $_GET['debug-set'] ) ) {
wp_cache_set( 'naxvog_test_obj1', $a );
wp_cache_set( 'naxvog_test_obj2', $s );
}
if ( isset( $_GET['debug-get'] ) ) {
var_dump( wp_cache_get( 'naxvog_test_obj1' ) );
var_dump( wp_cache_get( 'naxvog_test_obj2' ) );
}
} );There was a problem hiding this comment.
Should we check is_serialized() twice in maybe_unserialize()?
There was a problem hiding this comment.
I would rather prefer a conversion script running on plugin update resolving such issues but this might be a non trivial approach, would most likely require a LUA script and will take some time (best suited for action scheduler).
There was a problem hiding this comment.
I can't think of any valid way to serialize twice. Sure there might be serialized data within a serialized object but this is expected behaviour.
Have to look again but I'm fairly sure that I have not found any double serialized key our docker dev environment. Will have a look on my production redis instance. Should be fairly easy to find.
There was a problem hiding this comment.
OK found some instances (ran vim searching for [[:cntrl:]]s:[[:digit:]]\+:"O on a copy of the rdb database):
- Plugin Update Checker (option keys
puc_external_updates-[slug],puc_external_updates_theme-[slug]) - WPML (option keys:
wpml_config_index+ others) - Easy Social Share Buttons (seems to be using Plugin Update Checker as the option key
external_updates-easy-social-share-buttonssuggests) - Google Sitemap Generator (option key
sm_status)
There was a problem hiding this comment.
Can we simply solve this by running this twice?
redis-cache/includes/object-cache.php
Lines 1979 to 1985 in fbfc86f
There was a problem hiding this comment.
Have to look in the code of those plugins to confirm that this is not intended. If not we should find the cause for this double serialization instead.
There was a problem hiding this comment.
Running unserialize() twice seems risky, in case plugins do their own serialization.
|
@naxvog Thoughts on the latest push? |
| $value = @unserialize( $original ); | ||
| } | ||
|
|
||
| return is_object( $value ) ? clone $value : $value; |
There was a problem hiding this comment.
Why are we cloning the unserialized object right away?
includes/object-cache.php
Outdated
| $value = @unserialize( $original ); | ||
|
|
||
| // Just in case the data was serialized twice | ||
| if ( is_string( $value ) && $this->is_serialized( $value ) ) { |
There was a problem hiding this comment.
is_string test is the first test in the is_serialized method - we can drop the first condition.
There was a problem hiding this comment.
For reference the WordPress maybe_serialize function is as follows:
function maybe_serialize( $data ) {
if ( is_array( $data ) || is_object( $data ) ) {
return serialize( $data );
}
/*
* Double serialization is required for backward compatibility.
* See https://core.trac.wordpress.org/ticket/12930
* Also the world will end. See WP 3.6.1.
*/
if ( is_serialized( $data, false ) ) {
return serialize( $data );
}
return $data;
}Don't think we should follow the backward compatibility discussed in https://core.trac.wordpress.org/ticket/12930
|
Alright:
@naxvog: I haven't tested any of this, but I'm happy with the overall approch |
cd37474 to
a6513be
Compare
| * | ||
| * @return void | ||
| */ | ||
| public function run_migrations() { |
There was a problem hiding this comment.
To simplify things we could just flush the cache every time the plugin is updated.
Alternatively we should avoid polluting the options table with version specific entries - a general roc_version storing the last known version would be better. Migrations would only run if the current plugin version is newer.
My best guess is that this is never called. Thoughts @naxvog?
In 3.0 we should re-think the serialization.