Page MenuHomePhabricator

Notice: unserialize() Error when using Postgres
Closed, ResolvedPublic

Description

Author: alessandro

Description:
I have a problem with MediaWiki 1.11.0 and PostgreSQL 8.1.9 (from Ubuntu Server 6.06.1 LTS).

Well, my little problem started today, when I do an update in MediaWiki from 1.10.1 to 1.11.0.

Everything worked fine, however, I'm getting the error message (in the top) in the Main Page and in some others:

Notice: unserialize() [function.unserialize]: Error at offset 0 of 4197 bytes in /var/www/wiki/includes/BagOStuff.php on line 392


Version: 1.11.x
Severity: enhancement
OS: Linux

Details

Reference
bz11292

Related Objects

View Standalone Graph
This task is connected to more than 200 other tasks. Only direct parents and subtasks are shown here. Use View Standalone Graph to show more of the graph.
StatusSubtypeAssignedTask
InvalidNone
ResolvedNone

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 9:56 PM
bzimport added a project: MediaWiki-Parser.
bzimport set Reference to bz11292.
bzimport added a subscriber: Unknown Object (MLST).

japsu wrote:

I'm experiencing this problem too. Gentoo, Apache 2.2.4, PHP 5.2.4, PostgreSQL 8.2.4.

purluno wrote:

(MediaWiki 1.11.0 with PostgreSQL 8.2.4, PHP 5.2.1)

The cause of this problem is inconsistency in DatabasePostgres.php.

function encodeBlob($b) on line 1141 just returns pg_escape_bytea($b).

function addQuotes($s) on line 1152 returns escaped string of $s which is surrounded by quotes.

These functions are called to escape serialized data by 'set' function in BagOStuff.php.

Consequently, serialized data is escaped by pg_escape_string(pg_escape_bytea($b)).

So in database, serialized data is stored as an abnormally escaped string.

After receiving the data from database, pg_unescape_bytea just replaces two backslashes to one backslash.

It seems that function 'addQuotes' expects its bytea argument to be an array.

So it is resolved if serialized data is passed to 'addQuotes' in array form.

Emergency fix could be made like below:

function encodeBlob($b) {

return array(0, pg_escape_bytea($b)); # emergency fix

}

isaac.waldron wrote:

I have this problem as well on FreeBSD 6.2 with PostgreSQL 8.2

This is a tricky problem: there are places where we need the raw decoded string passed back in, such as the select statements in Math.php. The problem is that the function select() in Database.php also uses arrays, but to indicate a range of values.Thus there is no easy way to indicate that a value does not need quoting. One option may be to use a special key that select() can recognize and not treat as an array of values. Looking into it...

purluno wrote:

How about to create a class? It seems that DatabaseOracle.php has a similar class. And we can use a magic method __toString() in PHP 5.

class PostgresBlob {

var $mData;

function __construct($data) {
    $this->mData = $data;
}

function __toString() {
    return $this->mData;
}

}

...

(in class DatabasePostgres)

function encodeBlob( $b ) {

return new PostgresBlob(pg_escape_bytea( $b ));

}

function addQuotes( $s ) {

...
} else if ($s instanceof PostgresBlob) {
    return "E'$s'";
...

}

Yes, that's the direction I've been going, except putting the class in Database.php, as we'll need to check it from within there as well, and other DBs will also need to use it.

Created attachment 4133
Proposed Blob class

How does this look? I'll also have the updater blow away any existing caches.

Attached:

purluno wrote:

Added code in Database.makeList() should be removed. Because it calls the function addQuotes() with the unwrapped string value of the Blob object, so addQuotes() which is called by it always fail to recognize the value as a blob. __toString() is a magic method in PHP 5. It's automatically called when its object should be used as a string. So that code isn't needed.

Other changes seem right.

__toString() is a magic method in PHP 5. It's automatically called when its
object should be used as a string. So that code isn't needed.

Maybe in theory, but in testing it's trying to insert strings such as 'Object id #20' if the explicit call to toString is removed. Still getting unserialize offset errors anyway, will try again later tonight. Suggestions welcome, a working serialize->blobencode->blobdecode->unserialize example is what I'm aiming for.

purluno wrote:

I use PHP 5.2.1 and it works properly. So I checked the problem from PHP 5 changelog, and the behavior of the method is different between versions.

Version 5.0.0 Release Candidate 1
18-Mar-2004
...
Changed __toString() to be called automatically only with print and echo statements. (Andi)

Version 5.2.0
02-Nov-2006
...
Changed __toString() to be called wherever applicable. (Marcus)

If the next mediawiki release should keep the required version of PHP as same as current(just PHP 5), it'll be good to move that explicit call into the function addQuotes() like below:

function addQuotes( $s ) {

...
} else if ($s instanceof Blob) {
    return "'{$s->__toString()}'";
...

}

How about it?

Now I should sleep as it's 3 o'clock in Korea now, I'll be able to check a new comment tomorrow.

Still not able to get this working without unserialize errors. I'm tempted to switch to base64. I starting to suspect that pg_escape_bytea and pg_unescape_bytea are broken in at least some versions.

Okay, finally figured it out, thanks for the help here. See r26040.

joebarger8 wrote:

I have applied the Bug Fix to Database.php and DatabasePostgres.php but still have the same problem. I am still recieving:
Notice: unserialize()[function.unserialize]: Error at offset 0 of 616 bytes in .../includes/BagOStuff.php on line 392

Is this the only fix to this bug? Did the fix work for anybody else? It's a little frustrating because everything online points to this fix, but I've tried it and it's not working for me. Thanks.

niccolo wrote:

Problem not solved here.

Upgraded MediaWiki from 1.9.3 to 1.11.0, then the unserialize() error.
Copied Database.php and DatabasePostgres.php from svn trunk, but this do not solve the problem.

  • Debian Testing (Lenny)
  • Postgres 8.2.4
  • PHP 5.2.3

niccolo wrote:

Sorry, sorry, sorry!!! The problem is solved.

May be some aggressive cache did keep the error showing (shift-reload was not sufficient).
I cleared the browser cache and restarted Apache server : the error is disappeared.

I re-close the bug, hoping that Comment #13 is a false alarm, like mine.

Sorry for annoying.

berend wrote:

Unfortunately the emergency fix nor the patch worked for me. Still see the same error message. And yes, did stop and start apache, but that made no difference.

PostgreSQL: 8.1.10.
PHP 5.1.4
Linux (LFS).

Also when I applied the patch it said there were a few lines of difference, so not sure against what version the patch was made.

berend wrote:

Perhaps helpful if I give the exact error messages:

Notice: unserialize() function.unserialize: Error at offset 0 of 2214 bytes in .../creationpedia/includes/BagOStuff.php on line 392

Notice: unserialize() function.unserialize: Error at offset 0 of 80 bytes in .../creationpedia/includes/BagOStuff.php on line 392

No time to dig into this at the moment, but make sure you clear out the old entries by doing "TRUNCATE TABLE objectcache" and "TRUNCATE TABLE querycache" as the patch will only fix new entries, not fix any with bad bytes already in the database.

berend wrote:

Nope, didn't do anything. I already had gone to new pages to check if that might be an issue, but the error keeps popping up on every page.

Can you try the revision of MediaWiki and see if that works for you? Which version of MW are you using?

berend wrote:

I'm using the version mentioned in this bug report. What do you mean with "Can you try the revision of MediaWiki"?

I meant the latest subversion revision of MediaWiki. Right now I cannot duplicate your problem, so it might help to see if it is something that was fixed between the version you are using and the latest. If it is not fixed, we ideally need some sort of duplicateable test.

cbandy wrote:

Revision 26040

Confirm that Comment #12 fixes this for me on Postgres 8.1.9 in MediaWiki 1.11.1

Attached:

Any luck on a newer revision, Berend?

berend wrote:

Went to use MySQL as that solved the problem. Unfortunately won't have time in the near future, so perhaps close as can't duplicate.

Yep, that's one way to solve it :) Thanks for the response, please reopen this bug if you see the problem again with Postgres in the future.

Jdforrester-WMF subscribed.

Migrating from the old tracking task to a tag for PostgreSQL-related tasks.