ID:               21957
 Updated by:       [EMAIL PROTECTED]
 Reported By:      [EMAIL PROTECTED]
-Status:           Open
+Status:           Verified
 Bug Type:         Session related
 Operating System: Linux (Debian/Testing)
-PHP Version:      4.3.0
+PHP Version:      4.3.1-dev
 New Comment:

Same result with latest CVS of PHP_4_3 branch.
There is an error message given:

"Notice: serialize() [function.serialize]: __sleep should return an
array only containing the names of instance-variables to serialize."

But it should propably store NULL there instead of mangling the object
totally.




Previous Comments:
------------------------------------------------------------------------

[2003-01-29 23:19:53] [EMAIL PROTECTED]

While there were a few bugs filed relating to _sleep and serialization
and sessions, none seemed to deal with the behavior described below.  A
few talk about Apache crashing under similar circumstances - there is
not crash, just a lot of unexpected behavior.
My appologies if this is a duplicate...


If the return statement if left out of the definition of __sleep in a
class, it appears that the serialization of this class is then an empty
string.

This seems fair enough, but it can cause strange behavior when
attempting to store the Object in a Session.  For simple data
structures it's not a problem, but for more complex ones the session
data string becomes mangled to the point where other (unrelated)
session objects are affected.

Consider the following simple script, in which the careless author has
forgotten to include the return statement for __sleep:

<?PHP
                                                                       
                                           
                                                                       
                                           
class Test
{
  var $a;
  var $b;
                                                                       
                                           
  function Test()
  {
    $this->a = 7;
    $this->b = 2;
  }
                                                                       
                                           
  function __sleep()
  {
    $this->b = 0;
  }
}
                                                                       
                                           
                                                                       
                                           
session_start();
                                                                       
                                           
echo 'Session at start of request:<br />';
echo '<pre>';
print_r($_SESSION);
echo '</pre><br />';
                                                                       
                                           
$t['one'] = 'this is a test string';
$t['two'] = new Test();
$_SESSION['test'] = $t;
$_SESSION['test2'] = "this is another test string";
                                                                       
                                           
echo 'Serialised session variable:<br />';
echo '-->'.serialize($_SESSION['test']).'<--';
echo '<br /><br />';
                                                                       
                                           
echo 'Session at end of request:<br />';
echo '<pre>';
print_r($_SESSION);
echo '</pre><br />';
                                                                       
                                           
                                                                       
                                           
?>


After clearing the session cookie (or starting a new browser session)
the original output of the page is as would be expected:


Session at start of request:

Array
(
)


Serialised session variable:
-->a:2:{s:3:"one";s:21:"this is a test string";s:3:"two";}<--

Session at end of request:

Array
(
    [test] => Array
        (
            [one] => this is a test string
            [two] => test Object
                (
                    [a] => 7
                    [b] => 0
                )

        )

    [test2] => this is another test string
)


The values in $_SESSION are fine.  One can see the problem with the
serialized version of the session variable quite clearly - while the
array supposedly contains 2 elements, there is no information on how to
reconstruct the second one.  Thus, this string cannot be unserialized.

Re-loading the page (so that the session data is read from the stored,
serialised data) produces the following output:

Session at start of request:

Array
(
    [test] => 
    [}test2] => this is another test string
)


Serialised session variable:
-->a:2:{s:3:"one";s:21:"this is a test string";s:3:"two";}<--

Session at end of request:

Array
(
    [test] => Array
        (
            [one] => this is a test string
            [two] => test Object
                (
                    [a] => 7
                    [b] => 0
                )

        )

    [}test2] => this is another test string
    [test2] => this is another test string
)


Notice the mangling of the session variables.  For good measure,
re-load the page once more to produce:

Session at start of request:

Array
(
    [test] => 
    [}}test2] => this is another test string
    [test2] => this is another test string
)


Serialised session variable:
-->a:2:{s:3:"one";s:21:"this is a test string";s:3:"two";}<--

Session at end of request:

Array
(
    [test] => Array
        (
            [one] => this is a test string
            [two] => test Object
                (
                    [a] => 7
                    [b] => 0
                )

        )

    [}}test2] => this is another test string
    [test2] => this is another test string
)


Further requests continue to add '}' characters to the strange session
variable.  With more complicated data structures (such as the one I
originally discovered this behavior in) the results of the mangling can
be much more bizzare and more serious.  Particularly worrying is that
the unrelated variable 'test2' was lost from the session on the first
re-load.  It is only restored in later requests because it is
explicitly set each time and is now guarded by the other phantom
variable.


Adding a proper return statement to __sleep fixes the problem.


While the obvious solution is 'make sure there is a return statement
inside __sleep', I'm concerned about the potential for mangling session
data because sessions are so often related to security.  Especially if
untrusted objects were being stored in session data, this could
potentially cause serious problems (at least, I imagine so).
At the very least, causing unexpected changes to session data is
difficult to deal with as a programmer - especially if you were not the
author of the offending class, since no indication of the problem is
given.

Perhaps objects with an empty serialisation could be treated as null? 
Or, perhaps the return value of __sleep could default to an empty
array?  Or perhaps leaving it out could trigger a warning?  Just
suggestions...

If you need any more info, please feel free to contact me.


  Ryan



------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=21957&edit=1

Reply via email to