Make WordPress Core

Opened 15 years ago

Closed 12 years ago

Last modified 9 years ago

#12930 closed defect (bug) (fixed)

Unserialize error?

Reported by: ipstenu's profile ipstenu Owned by:
Milestone: 3.0 Priority: high
Severity: major Version:
Component: General Keywords:
Focuses: Cc:

Description

I upgraded to 3.0 beta for testing and found that a couple plugins are giving me an odd error:

Warning: unserialize() expects parameter 1 to be string, array given in ...

This happens in two different plugins (JournalPress and Google Analyticator). WordPress works with the error, and JournalPress even posts to my blog AND my LJ.

Change History (21)

#1 @ocean90
15 years ago

  • Milestone Unassigned deleted
  • Resolution set to invalid
  • Status changed from new to closed

unserialize() is a PHP function.

unserialize() takes a single serialized variable(string) and converts it back into a PHP value. 

Please inform the plugin developers, its not a WordPress issue.

#2 @nacin
15 years ago

It might be from core however, i.e. something that changed from 2.9 to 3.0, but we need to know the line number and more information on how it gets triggered.

Please re-open if you have steps to reproduce.

#3 @ipstenu
15 years ago

If it had only been ONE plugin, I'd have agreed ocean90, but once it comes up twice, I get suspicious. And it ONLY happened once I upgraded to 3.0 (worked FINE in 2.9.x).

I can reproduce the LJ plugin every time I try and save ANY post while it's activated. And the Google Analyticator one just by trying to view the dashboard 'plugin'.

The problem is I'm the user, not the dev. I'll ping them for support and ask them to come here.

#4 @nacin
15 years ago

We can't do anything unless we know more about the error. At the very least, line numbers?

#5 @sivel
15 years ago

If I am correct in my assumption it is something with get_post_meta. I had to update a plugin for WP 3.0 to use maybe_unserialize instead of unserialize because get_post_meta is unserializing the data it returns.

#6 @ipstenu
15 years ago

I went to some examples for you:

Warning: unserialize() expects parameter 1 to be string, array given in /home/ipstenu/public_html/blog/wp-content/plugins/journalpress/jpconfig.php  on line 696

Warning: unserialize() expects parameter 1 to be string, array given in /home/ipstenu/public_html/blog/wp-content/plugins/journalpress/jpconfig.php on line 703

Warning: unserialize() expects parameter 1 to be string, array given in /home/ipstenu/public_html/blog/wp-content/plugins/journalpress/jpconfig.php on line 709

And I saw sivel's comment. Changing unserialize to maybe_unserialize fixes everything.

Interesting, that. I'm passing it on to the devs.

#7 @nacin
15 years ago

*sigh*. maybe_unserialize is only half of it. That plugin is trying to unserialize a result from get_post_meta(). The meta, options and transients APIs all handle that transparently. There should be no unserialize call there at all.

#8 @nacin
15 years ago

  • Milestone set to 3.0
  • Resolution invalid deleted
  • Status changed from closed to reopened

After some investigating (thanks sivel), looks like there may be something going on here. I want to look at this some more.

#9 @lupinek7
15 years ago

  • Keywords unserialize added
  • Priority changed from normal to high
  • Severity changed from normal to major

The same problem with get_option() – unexpectedly returns unserialized data in 3.0beta-1 (in 2.9 everything worked just fine).

#10 @nacin
15 years ago

We're looking into this. It comes out of a change to maybe_serialize() in r13673, which for a long while serialized already serialized data, and now no longer does. We'll probably revert this.

Bottom line is, plugin developers are using the _option, _meta, and _transient APIs horribly incorrectly for this change to cause problems.

These APIs already serialize and unserialize objects and arrays transparently. Thus, this works:

update_option( 'my_plugin_options', array( 'blah', 'foo', bar' ) );
get_option( 'my_update_plugins' ); // returns the array

Instead, far too many are doing this:

update_option( 'my_plugin_options', serialize( array( 'blah', 'foo', bar' ) ) );
unserialize( get_option( 'my_update_plugins' ) );

More or less, that means that you're serializing the data, then update_option is serializing serialized data, then get_option is unserializing it once, and unserialize is unserializing it again. r13673 breaks this, as update_option doesn't serialize the data a second time any more, causing the plugin's unserialize() to attempt to perform a second unserialize() on data that was only serialized once.

I will revert the changes in r13673. But please, update your plugins, spread the word.

#11 @nacin
15 years ago

(In [14074]) Revert changes to maybe_serialize() made in r13673. Do not prevent double-serialization of data. see #12930. see also #12416. xref #7347, r8100, r8372, and others.

#12 @ipstenu
15 years ago

nacin, thank you very much for tolerating my stupid-head explanation :) I am passing this on to every dev I know!

#13 @cavemonkey50
15 years ago

I apologize nacin for the incorrect serialization usage in Google Analyticator. Normally I'm aware of that usage of of the options API, but the code that caused a problem was written during a quick coding session and it must have slipped my mind.

Anyway, Google Analyticator 6.0.3 will have this fixed, regardless of what happens in core.

#14 @nacin
15 years ago

:-) No problems folks. We don't like breaking plugins even if the plugin is 'Doing It Wrong' in the eyes of the API. The change to maybe_serialize() was unintentional so we've switched it back.

#15 @nacin
15 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

#16 @hexalys
12 years ago

  • Cc themacmaster@… added
  • Keywords needs-patch added
  • Resolution fixed deleted
  • Status changed from closed to reopened
  • Version set to 3.5.1

Nacin, r13673 may have addressed those plugin error at the time, but you introduced a new cache defect.

In update_option() where your changed to $alloptions[$option] = $_newvalue; and wp_cache_set( $option, $_newvalue, 'options' );
$_newvalue should be kept $newvalue when it come to the cache, to remain consistent with the way add_option() works.

Right now add_option() store options as serialized while update_option() stores them as arrays which is very inconsistent.
It really messes things up, especially with a memory cache, where you suddenly may get unexpected arrays instead of serialized values, but can't really know for sure what you will get.

Last edited 12 years ago by hexalys (previous) (diff)

#17 follow-up: @ocean90
12 years ago

  • Keywords 3.0-beta unserialize needs-patch removed
  • Resolution set to fixed
  • Status changed from reopened to closed
  • Version 3.5.1 deleted

As this ticket was closed as fixed on a completed milestone, please open a new ticket or take a look at #23381

#18 in reply to: ↑ 17 @hexalys
12 years ago

Replying to ocean90:

As this ticket was closed as fixed on a completed milestone, please open a new ticket or take a look at #23381

OK thanks, I missed that ticket.

#19 @huynhquocnha
9 years ago

My error :
Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'SimpleXMLElement' is not allowed' in /home2/wp-includes/functions.php:384
Stack trace:
#0 /home2/wp-includes/functions.php(384): serialize(Object(SimpleXMLElement))
at web: http://vaytinchapdng.com/

Help me about this error, thank any one !

#20 follow-up: @dd32
9 years ago

@huynhquocnha you appear to be passing a SimpleXML element to an options/transient/cache function, which PHP doesn't support. Cast it to a string first or something.

Trac is not a support avenue, please use the WordPress Support Forums for further assistence.

#21 in reply to: ↑ 20 @huynhquocnha
9 years ago

Replying to dd32:

@huynhquocnha you appear to be passing a SimpleXML element to an options/transient/cache function, which PHP doesn't support. Cast it to a string first or something.

Trac is not a support avenue, please use the WordPress Support Forums for further assistence.

@dd32 thank

Note: See TracTickets for help on using tickets.