Bug #13229 - some analysing
| From: | Hans Spath | Date: | Thu, 13 Sep 2001 19:46:27 +0000 |
| Subject: | Bug #13229 - some analysing | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-65900@lists.php.net to get a copy of this message | ||
Hi f0lks,
I've just subscribed to this mailing list because I have a problem with session handling that seems to be a bug (the one described at http://www.php.net/bugs.php?id=13229).
I've spend a lot of time on analyzing session handling so I hope my results help somebody to fix this bug.
Before PHP 4.0.6 the problem was, that changes in $HTTP_SESSION_VARS were not saved if register_globals was enabled.
In PHP 4.0.6 the problem is, that changes in $HTTP_SESSION_VARS won't be saved if register_globals is enabled AND when the changed variable wasn't registered before that script call.
(Don't tell me I should turn off register_globals when I prefer to use $HTTP_SESSION_VARS - it's not my server I'm working on.)
I have written this example hoping it helps understanding what I mean:
( we need 3 files and register_globals turned on )
// file 1 "destroy.php"
session_start('test');
session_destroy();
// end file 1
// file 2 "bug.php"
if (! session_is_registered('foo')) {
echo 'Registering foo<br>';
session_register('foo');
$HTTP_SESSION_VARS['foo'] = 0; // *0*
}
echo ++$HTTP_SESSION_VARS['foo'];
// end file 2
// file 3 "bug_workaround.php"
if (! session_is_registered('foo')) {
echo 'Registering foo<br>';
session_register('foo');
$HTTP_SESSION_VARS['foo'] = 0; // *0*
$foo = & $HTTP_SESSION_VARS['foo']; // *1*
}
echo ++$HTTP_SESSION_VARS['foo'];
// end file 3
Call "destroy.php" then bug.php and you should see "Registering foo" and "1". Call bug.php many times and you will see each time only "1", what tells us foo is registered but it wasn't saved.
Call "destroy.php" then bug_workaround.php and you should see "Registering foo" and "1". Call bug_workaround.php many times and you will see it is working now!
After some analyzing I think I have understand and can explain how session handling works with register_globals enabled:
Session_start() creates references to all registered variables from $HTTP_SESSION_VARS['foo'] to $GLOBALS['foo'] (since PHP 4.0.6, see changelog, 2nd line *3*). After a script is completely processed and a session is active, php takes all registered variables from $GLOBALS and saves them as session data.
Applied to my example:
Now we start an -till now- unused session and register a variable 'foo' and set $HTTP_SESSION_VARS['foo'] to 0 (*0*). We increase $HTTP_SESSION_VARS['foo'] by 1. At the end of the script PHP tries to save $GLOBALS['foo'] to the session what fails because $GLOBALS['foo'] is not a reference to $HTTP_SESSION_VARS['foo'].
*2*
We start it again. Session_start() doesn't restore 'foo' to $GLOBALS['foo'] because it was unable to save it, then it tries to create a reference from $GLOBALS['foo'] to $HTTP_SESSION_VARS['foo'] what fails, because there is no $GLOBALS['foo']. We increase $HTTP_SESSION_VARS['foo'] (which didn't exist before this step) by 1. Now, at the end of the script PHP tries again to save $GLOBALS['foo'] to the session what fails because the creation of the reference $GLOBALS['foo'] <-> $HTTP_SESSION_VARS['foo'] failed.
(continue reading at *2* ;-)
To fix this behavior, I create the first reference by hand (see *0* and *1*).
If you have further questions, do not agree to my explanation or think I'm the most stupid man on earth feel free to send me email.
*3* = ChangeLog PHP 4.0.6: "Made $HTTP_SESSION_VARS['foo'] and $foo be references to the same value when register_globals is on. (Andrei)"
Hans Spath <dev@generalprotectionfault.de>
PS:
Please excuse my perhaps poor english ;)
(I didn't use to write in english.)