php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #20728 $_SESSION can be broken with "global"
Submitted: 2002-11-29 13:53 UTC Modified: 2002-12-15 04:04 UTC
Votes:3
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (50.0%)
From: mikemc-phpbug at contactdesigns dot com Assigned:
Status: No Feedback Package: Session related
PHP Version: 4.2.3 OS: Linux 2.4.x
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2002-11-29 13:53 UTC] mikemc-phpbug at contactdesigns dot com
First, please ignore my comment on bug #17959, I have further investigated this
issue to narrow down exactly what is causing it and have written a test script
so that you can verify this on your end as well.  This bug (should you accept to
proclaim it a vaild bug) relates to the autoglobal $_SESSION.  More 
specifically, $_SESSION can be broken so that the values set in it are not 
actually saved.  First, lets see how it can be broken:

<?php

session_start();

echo 'Before session modifications (what got saved to disk):<br><pre>';
var_dump($_SESSION);

$_SESSION['foobar'] = 1;
global $_SESSION;
$_SESSION['foobar'] = 2;

echo '</pre>After session modifications:<br><pre>';
var_dump($_SESSION);

?>

When you run this, and then hit reload (since you must run it at least twice to
see what actually got saved by session), the browser will output this:

Before session modifications (what got saved to disk):

array(1) {
  ["foobar"]=>
  int(1)
}

After session modifications:

array(1) {
  ["foobar"]=>
  int(2)
}


So, you can see that the line "global $_SESSION;" essentially breaks session - 
the "2" never gets saved to disk.  If we comment out "global $_SESSION;", it 
works and the browser outputs this (after you hit reload twice):

Before session modifications:

array(1) {
  ["foobar"]=>
  int(2)
}

After session modifications:

array(1) {
  ["foobar"]=>
  int(2)
}


So now you are asking that is interesting, but why would you ever want to
"global" an autoglobal.  Good question!  There would be no purpose in doing this
since $_SESSION is always in scope.  Well, this bug presented itself to me in
an application where there was a reference to a portion of $_SESSION.  Since
the application is over 5000 lines of code, we will view a highly condensed
test version of this:

<?php

session_start();

echo 'Before session modifications:<br><pre>';
var_dump($_SESSION);

$_SESSION['foobar'] = 1;
$foobar = $_SESSION['foobar'];
global $foobar;
$foobar = 3;

echo '</pre>After session modifications:<br><pre>';
var_dump($_SESSION);

?>

Outputs:

Before session modifications:

array(1) {
  ["foobar"]=>
  int(1)
}

After session modifications:

array(1) {
  ["foobar"]=>
  &int(1)
}

And if we comment out "global $foobar;" we get: 

Before session modifications:

array(1) {
  ["foobar"]=>
  int(1)
}

After session modifications:

array(1) {
  ["foobar"]=>
  &int(3)
}


This is the behavior we would expect with a reference given the output we saw in
the earlier example.  But why would we run "global $foobar;" if it is already
in scope?  In my application, other developers use the code for purposes of
building other applications.  Since I don't know what scope they are including
my code in, I have to assume it is NOT in global scope and therefore run
"global" on some variables that I will need.  In this sort of situation it makes
sense to call "global" just to make sure that you have what you need.  The
problem is that if they did include it in global scope that it busts session!!!

Anyways, I look forward to your response.  I have already implemented a
workaround to this problem but think it is important that the PHP QA/BUG teams
are aware of this issue.

Thank You for you time - everyone appreciates the work that you do for PHP

P.S.  My configure line is:

'./configure' '--enable-memory-limit' '--with-mysql=/usr/local/mysql' '--with-zlib' '--with-apache=../apache_1.3.27' '--enable-inline-optimization' '--with-curl=/usr/local' '--with-mcrypt=/usr/local'

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-11-29 15:23 UTC] sniper@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php4-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php4-win32-latest.zip
 [2002-11-29 17:59 UTC] mikemc-phpbug at contactdesigns dot com
Hello,

I have compiled the latest snap shot at http://snaps.php.net/php4-latest.tar.gz.  The only change I had to make for the PHP compiling process was to update my version of curl since the snapshot requires curl-7.10.2 (the latest stable release).  It compiled fine, I restarted the web server, and the same problem still occurs with the same code from my original bug post.

Please let me know if you need any additional information.

Mike
 [2002-11-29 20:58 UTC] sniper@php.net
Don't use global with the autoglobal arrays.

 [2002-12-01 16:07 UTC] mikemc-phpbug at contactdesigns dot com
Hello,

I don;t think it is quote as easy as saying "Don't use global with the autoglobal arrays.".  Please read my original bug post.  I went out of my way to be very detailed so that I don't waste your time - this does nobody any good though if you don't take the time to read it.  More specifically, this is the part I am referring to:

<ORIGNAL BUG POST>

So now you are asking that is interesting, but why would you ever want to "global" an autoglobal.  Good question!  There would be no purpose in doing this since $_SESSION is always in scope.  Well, this bug presented itself to me in an application where there was a reference to a portion of $_SESSION. Since the application is over 5000 lines of code, we will view a highly condensed test version of this:

<?php

session_start();

echo 'Before session modifications:<br><pre>';
var_dump($_SESSION);

$_SESSION['foobar'] = 1;
$foobar = $_SESSION['foobar'];
global $foobar;
$foobar = 3;

echo '</pre>After session modifications:<br><pre>';
var_dump($_SESSION);

?>

</ORIGNAL BUG POST>

So the bug presents itself when you "global" a reference to an array element of an autoglobal as well.  Perhaps, I should have used this as the original code example.  Please take the time to read the full bug post.

Thank You,

Mike
 [2002-12-01 16:13 UTC] sniper@php.net
I get this normal output:

Before session modifications:

array(1) {
  ["foobar"]=>
  int(1)
}

After session modifications:

array(1) {
  ["foobar"]=>
  int(1)
}


No bug here. (using PHP 4.3.0-dev)

 [2002-12-01 19:06 UTC] mikemc-phpbug at contactdesigns dot com
Hello,

This code is incorrect - I must have pasted over the code after I modified it during testing as $foobar is not a reference, but a copy.  Here is what it should be (please note that you will have to hit reload after the first hit as session gets created on the first hit - so load it and hit reload - and then view the output):

<?php

session_start();

echo 'Before session modifications:<br><pre>';
var_dump($_SESSION);

$_SESSION['foobar'] = 1;
$foobar =& $_SESSION['foobar'];
global $foobar;
$foobar = 3;

echo '</pre>After session modifications:<br><pre>';
var_dump($_SESSION);

?>
 [2002-12-01 19:48 UTC] sniper@php.net
I still don't see any bug here..using references with _SESSION is not really useful as only the value is stored..

You think it should stay as a reference?



 [2002-12-15 04:04 UTC] sniper@php.net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Open". Thank you.


 [2003-03-31 21:10 UTC] alex at avannaproductions dot com
I'm experiencing this problem with 4.3. I did a global find and replace across many php files to change $HTTP_SESSION_VARS to $_SESSION. Then I went through and removed all the functions (like session_register) that are no longer needed. The one thing I FORGOT to remove was the line "global $HTTP_SESSION_VARS" each time it appeared. Instead my find and replace just changed it to "global $_SESSION". Seems to me that the line "global $_SESSION" should be ignored by PHP since it is redundant, rather than preventing values from being set. It could at least give a warning but still work. Perhaps that is the best method since it might prevent a script from breaking, yet still alert the developer he/she is doing something wrong.
 
PHP Copyright © 2001-2023 The PHP Group
All rights reserved.
Last updated: Wed Feb 08 11:03:42 2023 UTC