Skip to content

Loading…

DDC-3120: Warning: Erroneous data format for unserializing PHP5.6+ #3897

Closed
doctrinebot opened this Issue · 38 comments

2 participants

@doctrinebot

Jira issue originally created by user techkey:

Hi all,

There seems to be something strange going on in the method newInstance() of the class \Doctrine\ORM\Mapping\ClassMetadataInfo.

The original class method looks like this:

{quote}\Doctrine\ORM\Mapping\ClassMetadataInfo#newInstance(){quote}

    {
        if ($this->_prototype === null) {
            $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
        }

        return clone $this->_prototype;
    }

What happens now when a class that implements \Serializable is that a "Warning: Erroneous data format for unserializing" shows up and the function unserialize() returns false.

That is because a class that implements \Serializable is expected to have the letter 'C' in the serialize string instead of the letter 'O'.

I've made a quick work-around like this:

{quote}\Doctrine\ORM\Mapping\ClassMetadataInfo#newInstance(){quote}

    {
        if ($this->_prototype === null) {
            $this->_prototype = @unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
            if ($this->_prototype === false) {
                $this->_prototype = unserialize(sprintf('C:%d:"%s":0:{}', strlen($this->name), $this->name));
            }
        }

        return clone $this->_prototype;
    }

That seems to work in my isolated tests and with Symfony2 and Doctrine2 and FOSUserBundle together.

I've noticed this because the Model\User class from FOSUserBundle implements \Serializable.

I had to implement a check in Model\User class because when using {{'C:%d:"%s":0:{}'}} the $serialized parameter of the unserialize method in the Model\User class is a empty string then.

That warning seems only to happen with PHP5.6+. PHP5.5.12 and below doesn't show that warning.

I hope someone can shine some light on this, thank you,

Cornelis.

@doctrinebot

Comment created by @ocramius:

Indeed, for PHP 5.4+ we should use ReflectionClass#newInstanceWithoutConstructor()

@doctrinebot

Comment created by techkey:

Just tested it. That works as expected, far more better then the dirty hacks I did, thanks a lot!

Any idea when this would be implemented into the code?

@doctrinebot

Comment created by @ocramius:

Send a pull request and I'll merge it later today (we could also need a failing test with an entity implementing the Serializable interface)

@doctrinebot

Comment created by evertharmeling:

Seems to be a problem in the latest PHP 5.4 version too.

#1045

@doctrinebot

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1045] was closed:
#1045

@doctrinebot

Comment created by rkmax:

I am facing this same error i have PHP 5.5.13, I'm using Symfony, Doctrine ORM and FOSUserBUndle

@doctrinebot

Comment created by @ocramius:

[~rkmax] the patch landed in master (2.5.x) for now.

@doctrinebot

Comment created by @ocramius:

Merged via DDC-3147

@doctrinebot

Comment created by tbuhk:

When can we expect the version with this bugfix?

@doctrinebot

Comment created by gnuk:

Why don't you tag 2.4.3 version with this fix ? Because the error is already present in PHP 5.5.13 which is a stable version and it's a blocking issue when you're using FOSUserBundle for example. There is also no opened issue refering this version and the due date is in april.

@doctrinebot

Comment created by j.perovic:

I'm still seeing this bug, although my PHPVERSIONID is 50600 :(

So, version based condition is no good...

@doctrinebot

Comment created by @ocramius:

The approach to be taken for 50600 is still under discussion in php-internals.

@doctrinebot

Comment created by techkey:

Hi all,

I've just downloaded PHP5.6RC1 and updated doctrine and the error is back indeed.

A little peek at the code starting on line 866 of file Doctrine\ORM\Mapping\ClassMetadataInfo.php shows this:

    public function newInstance()
    {
        if ($this->_prototype === null) {
            if (PHP*VERSION_ID === 50429 || PHP_VERSION*ID === 50513) {
                $this->_prototype = $this->reflClass->newInstanceWithoutConstructor();
            } else {
                $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
            }
        }

        return clone $this->_prototype;
    }

As can be seen, PHP5.6 is out of the picture, it only checks for the exact versions 5.4.29 and 5.5.13.

So for the code to work correctly on PHP5.6 one can add PHP5.6 to the test condition, or just skip the test all together if you don't mind the old PHP5.3. According to PHP, ReflectionClass::newInstanceWithoutConstructor is available since PHP >= 5.4.0.

Greetings, Cornelis.

@doctrinebot

Comment created by @ocramius:

As I already pointed out, this is still being discussed in php internals. See http://news.php.net/php.internals/75009

This won't be dealt with in 5.6 until there's either a stable release or internals decides what has to be done.

@doctrinebot

Comment created by @ocramius:

Also, ReflectionClass#newInstanceWithoutConstructor() still doesn't cover the pre-existing "hack" using unserialize, so we're still waiting for a reliable API from PHP core.

@doctrinebot

Comment created by chasen:

Using PHP 5.6RC2 and ORM 2.4.4 I am still experiencing this issue. I have also tested with PHP 5.5.15 and I am still getting the issue. Do i need to be using a different build of ORM to have the fix applied?

@doctrinebot

Comment created by pascall:

Hi,
I'm using 5.6.0beta3 and ORM 2.4.4 and i have the same probleme
Warning: Erroneous data format for unserializing .. in orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php line 872

and in current code in ClassMetadataInfo.php line 872 is :

public function newInstance()
{
    if ($this->_prototype === null) {
        if (PHP*VERSION_ID === 50429 || PHP_VERSION*ID === 50513) {
            $this->_prototype = $this->reflClass->newInstanceWithoutConstructor();
        } else {
            $this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
        }
    }

    return clone $this->_prototype;
}
@doctrinebot

Comment created by evertharmeling:

As stated by Marco Pivetta; "This won't be dealt with in 5.6 until there's either a stable release or internals decides what has to be done.". And besides that 5.6 still is in development, not stable.
If you still want to use 5.6 you can fork the code and extend the 5.4 / 5.5 check to support 5.6.

@doctrinebot

Comment created by chasen:

5.6 has an RC which should mean a stable API, and that only bugs will be fixed before an official stable release?

@doctrinebot

Comment created by evertharmeling:

Looking at http://news.php.net/php.internals/75966 it's still being discussed, and they are planning to have it fixed in RC3.

@doctrinebot

Comment created by @ocramius:

Internals still didn't get to a clear decision. Until then, we won't support 5.6 officially.

@doctrinebot

Comment created by Ronan:

Same error encountered with PHP 5.5.13 (cli) (built: May 30 2014 10:43:29)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies
with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans

(PHP 5.5 installed via http://php-osx.liip.ch/)

@doctrinebot

Comment created by @ocramius:

[~Ronan] what D2 version? We fixed it for 2.4.x (temporarily)

@doctrinebot

Comment created by Ronan:

My bad: reading my composer.lock: doctrine/orm, v2.4.2, ref 0363a55, "time": "2014-02-08 16:35:09"... Well.. this is was an old one !

composer update fixed it. Sorry for disturbing.

@doctrinebot

Comment created by chasen:

Im still getting this error running php 5.6RC2 and the dev-master(6ac19b0) build of D2/orm. Am i missing something?

@doctrinebot

Comment created by @ocramius:

This was semi-fixed in PHP5.6-RC3, and it will be patched into ORM once doctrine/instantiator is out

@doctrinebot

Comment created by chasen:

Ok good to know. Thanks

@doctrinebot

Comment created by @ocramius:

Not yet fixed for PHP 5.6

@doctrinebot

Comment created by @ocramius:

Provided a hotfix proposal at #1109 - please check it out with PHP 5.6.0-RC3 or later

@doctrinebot

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1109] was closed:
#1109

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot

Comment created by @ocramius:

Due to a new introduced dependency, this issue will only be solved for PHP 5.6 in 2.5.0 and later.

@doctrinebot

Comment created by @doctrinebot:

A related Github Pull-Request [GH-1109] was assigned:
#1109

@doctrinebot

Comment created by dominik.zogg@gmail.com:

@ocramius would be great if there where backports for 2.4 and 2.3

@doctrinebot

Comment created by r1pp3rj4ck:

I agree with Dominik, we'd like to use the latest stable version and would need this patch.

@doctrinebot

Comment created by @ocramius:

This has been backported in DDC-3339

@doctrinebot

Comment created by sysko:

I still have this error even 2.5.0 and PHP5.6
https://travis-ci.org/allan-simon/oauth2-symfony2-vagrant-fosuserbundle/jobs/62429219

@Ocramius Ocramius was assigned by doctrinebot
@doctrinebot doctrinebot added this to the 2.4.6 milestone
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.