From:             [EMAIL PROTECTED]
Operating system: Linux (Debian/Testing)
PHP version:      4.3.0
PHP Bug Type:     Session related
Bug description:  returnless __sleep mangles session data

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 bug report at http://bugs.php.net/?id=21957&edit=1
-- 
Try a CVS snapshot:         http://bugs.php.net/fix.php?id=21957&r=trysnapshot
Fixed in CVS:               http://bugs.php.net/fix.php?id=21957&r=fixedcvs
Fixed in release:           http://bugs.php.net/fix.php?id=21957&r=alreadyfixed
Need backtrace:             http://bugs.php.net/fix.php?id=21957&r=needtrace
Try newer version:          http://bugs.php.net/fix.php?id=21957&r=oldversion
Not developer issue:        http://bugs.php.net/fix.php?id=21957&r=support
Expected behavior:          http://bugs.php.net/fix.php?id=21957&r=notwrong
Not enough info:            http://bugs.php.net/fix.php?id=21957&r=notenoughinfo
Submitted twice:            http://bugs.php.net/fix.php?id=21957&r=submittedtwice
register_globals:           http://bugs.php.net/fix.php?id=21957&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=21957&r=php3
Daylight Savings:           http://bugs.php.net/fix.php?id=21957&r=dst
IIS Stability:              http://bugs.php.net/fix.php?id=21957&r=isapi
Install GNU Sed:            http://bugs.php.net/fix.php?id=21957&r=gnused

Reply via email to