Opened 12 years ago
Last modified 5 months ago
#28701 new defect (bug)
Deleted option is not deleted if value was ever null
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | 2.2 |
| Component: | Options, Meta APIs | Keywords: | has-patch has-unit-tests dev-feedback |
| Focuses: | Cc: |
Description
If an autoloaded option ever contains null, it will cease to be autoloaded after this. It will then be stored in the individual option cache (wp_cache_get('optname', 'options')), rather than the autoloaded options. The autoloaded option cache will then contain optname with the value null (and isset(null) === false).
Typically, this would be fine, but delete_option checks the database autoload value directly. It then only attempts to delete this from the autoload options cache (which again fails because of an isset check).
After deleting, the value is still stored in the object cache (!!!), causing it to return a value despite not existing in the database.
As far as I can tell, this has existed since r4855 (WP 2.2).
To reproduce (requires external object cache to be enabled):
// Add the option with initial value set to null add_option( 'testingkey', null ); // Update to real value update_option( 'testingkey', 'realvalue' ); // Delete the option completely delete_option( 'testingkey' ); // Check the value var_dump( get_option( 'testingkey', 'default' ) );
Expected result:
string(7) "default"
Actual result:
string(9) "realvalue"
Attachments (1)
Change History (11)
This ticket was mentioned in IRC in #wordpress-dev by rmccue. View the logs.
12 years ago
#3
@
12 years ago
Using https://gist.github.com/rmccue/4a0dadc68aa4e75c851f as a workaround for now. Will try and patch soon.
#5
@
10 years ago
This needs unit tests.
The change suggested in [28701.diff] seems innocuous to me, but it also doesn't seem to address the root problem. At a glance, it looks to me like we ought to fix the cache-busting logic in update_option(). It currently does this:
if ( ! defined( 'WP_INSTALLING' ) ) {
$alloptions = wp_load_alloptions();
if ( isset( $alloptions[$option] ) ) {
$alloptions[ $option ] = $serialized_value;
wp_cache_set( 'alloptions', $alloptions, 'options' );
} else {
wp_cache_set( $option, $serialized_value, 'options' );
}
}
But maybe (a) that first isset() should be array_key_exists(), and maybe (b) we should be more aggressive about invalidating both possible cache locations. (Though I want to careful about messing with 'alloptions' concurrency issues.)
This ticket was mentioned in Slack in #core-multisite by jjj. View the logs.
9 years ago
This ticket was mentioned in Slack in #core-editor by manooweb. View the logs.
5 years ago
This ticket was mentioned in PR #9643 on WordPress/wordpress-develop by @abcd95.
5 months ago
#9
- Keywords has-unit-tests added; needs-unit-tests removed
Also occurs if you use
update_optionlater rather than adding withnull: