WordPress.org

Make WordPress Core

Opened 11 months ago

Last modified 11 months ago

#39811 new defect (bug)

Bug maybe_unserialize() broke mysql data.

Reported by: ivijanstefan Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 4.7.2
Component: Database Keywords:
Focuses: Cc:

Description

I have an issue what is realated to maybe_unserialize() function.

Example:

When someone made MySQL export or backup and you want that data to import in database again, widgets, some plugin setup, some template setup, particular WPBakery Visual Composer or similar visual editors lost it's setup.

To get all work well I change function into this:

function maybe_unserialize( $original ) {
    if ( is_serialized( $original ) ) {
        $fixed = preg_replace_callback(
            '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|i:|o:|N;))!s',
            'serialize_fix_callback',
            $original );
        return @unserialize( $fixed );
    }
    return $original;
}
function serialize_fix_callback($match) { return 's:' . strlen($match[2]); }

-wit this code I get all data to work well but I'm unable to install new plugins or made any kind of update.

What to do with it, how to fix this problem and can you made some update to this code or add some solution to not happen this problems?

Here is also my StackOwerflow question: http://wordpress.stackexchange.com/q/255591/82023

Thanks!

Change History (4)

#1 follow-up: @SergeyBiryukov
11 months ago

  • Component changed from General to Database
  • Focuses administration template removed

Hi @ivijanstefan, welcome to WordPress Trac! Thanks for the ticket.

A similar issue was previously reported in #21109. There are two typical reasons that might cause this:

  • The DB_CHARSET value in wp-config.php doesn't match the actual DB charset (e.g. latin1 vs. utf8_general_ci).
  • The serialized data has been tampered with, e.g. by using search/replace incorrectly and breaking string lengths. The Database Search and Replace script might be helpful in that case to perform search/replace correctly.

#2 @swissspidy
11 months ago

The Database Search and Replace script might be helpful in that case to perform search/replace correctly.

Or the amazing WP-CLI of course :-)

#3 in reply to: ↑ 1 @ivijanstefan
11 months ago

Replying to SergeyBiryukov:

Hi @ivijanstefan, welcome to WordPress Trac! Thanks for the ticket.

A similar issue was previously reported in #21109. There are two typical reasons that might cause this:

  • The DB_CHARSET value in wp-config.php doesn't match the actual DB charset (e.g. latin1 vs. utf8_general_ci).
  • The serialized data has been tampered with, e.g. by using search/replace incorrectly and breaking string lengths. The Database Search and Replace script might be helpful in that case to perform search/replace correctly.

Good point, I not use that tool in this case. Generaly, database is in utf8_general_ci format and that can be issue.

But question:

Why you not made some "switching" function or something universal what cover this issue and fix problems? When I ore some other developer want to made fast fix we work directly in database without plugins. Also if we want to move WP from server to other server, we just do export, find/replace path and import new in database. Also when you do some massive migrations from server to server where is 100, 200, 1000 installations, we don't want to install plugins per websites We need to export SQL and import on new server.

Just chatting about this issue and I see a lot problems regarding this.

Thanks!

Last edited 11 months ago by ivijanstefan (previous) (diff)

#4 @ivijanstefan
11 months ago

I not fix this issue with any kind of database tools but I made an workable solution for maybe_unserialize():

function maybe_unserialize( $original ) {
	$url = strtolower('http'.(isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) ? 's' : '').'://'.@$_SERVER['HTTP_HOST'].@$_SERVER['REQUEST_URI']);
	
	if(strpos($url,'plugins') !== false || strpos($url,'update-core.php') !== false || strpos($url,'install') !== false || strpos($url,'edit-comments.php') || strpos($url,'disqus') !== false || strpos($url,'comment') !== false || strpos($url,'discussion') !== false)
	{
		if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
			return @unserialize( $original );
	}
	else
	{
		if ( is_serialized( $original ) ) {
			$fixed = preg_replace_callback(
				'!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|i:|o:|N;))!s',
				'serialize_fix_callback',
				$original );
			return @unserialize( $fixed );
		}
	}
    return $original;
}
function serialize_fix_callback($match) { return 's:' . strlen($match[2]); }

With this solution wordpress works well.

Note: See TracTickets for help on using tickets.