php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #25708 extract($GLOBALS, EXTR_REFS); can corrupt the $GLOBALS array.
Submitted: 2003-09-30 18:23 UTC Modified: 2004-08-09 00:36 UTC
From: cdragon at draconic dot com Assigned:
Status: Closed Package: Variables related
PHP Version: 4CVS-2003-09-30 (stable) OS: Windows 2000 Server
Private report: No CVE-ID:
 [2003-09-30 18:23 UTC] cdragon at draconic dot com
Description:
------------
Using extract($GLOBALS, EXTR_REFS); can cause the left hand side of two globals set "by-value" equal to one-another to become corrupted in the $GLOBALS array.  Hard to explain in English, but easier to see in the code below.

Reproduce code:
---------------
$sortColumn = "Affinity";
// Using "$lastSortColumn = substr($sortColumn, 0);" fixes the bug
$lastSortColumn = $sortColumn;

print "sort=" . $GLOBALS['sortColumn'] . " lastsort=" . $GLOBALS['lastSortColumn'] . "<p>";
extractGlobs();
print "sort=" . $GLOBALS['sortColumn'] . " lastsort=" . $GLOBALS['lastSortColumn'] . "<p>";

function extractGlobs()
{
  // Commenting out the line below fixes the bug.  So does not using the EXTR_REFS flag.
  extract($GLOBALS, EXTR_REFS);
}

Expected result:
----------------
sort=Affinity lastsort=Affinity
sort=Affinity lastsort=Affinity


Actual result:
--------------
sort=Affinity lastsort=Affinity
sort=Affinity lastsort=

or, randomly, you get an access violation instead:

PHP has encountered an Access Violation at 02CFF32F
(the 02CFF32F is variable)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-09-30 20:57 UTC] sniper@php.net
In short: Don't do this.

Longer version: GLOBALS is special variable, using extract() on it is a) pointless, b) stupid, c) useless.

GLOBALS references itself in it, when you try to extract it's contents as references, you'll end up with circular references which of course will cause a crash.

 [2003-09-30 21:36 UTC] cdragon at draconic dot com
Well, thank you for your quick (but rude) response.

It is certainly not useless (or stupid) to extract references to globals.  Extracting them without using the REFS flag creates deep copies of every variable (if I understand things correctly), which is very wasteful of resources.  More importantly, you can't modify the contents of a global string unless you extract with REFS or use an alternate method.  For example:

$var = "x";
extrTest();
print "var=$var<p>";

function extrTest() {
  extract($GLOBALS);
  //global $var;
  //extract($GLOBALS, EXTR_REFS);
  //$GLOBALS["var"] = "y";
  $var = "y";
}

Will print "var=x" instead of the desired "var=y" (which you can get using any of the commented-out lines).  Since there are obviously other syntactic alternatives, I don't _have_ to use the REFS method.  However, I would certainly consider it a serious bug that you can cause PHP to access violation and exhibit randomish, hard to diagnose errors  by doing something that actually _works most of the time_, serves a valid purpose, seems like it should work (without knowing some things about PHP's inner workings), and is not even cautioned against anywhere in the documentation that I can find.
 [2003-10-02 18:49 UTC] moriyoshi@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.


 [2004-08-09 00:36 UTC] moriyoshi@php.net
Closely related to bug #29493.

 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 24 21:01:55 2014 UTC