php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #54131 _SERVER, _ENV access via $$ shows Notice
Submitted: 2011-03-02 04:52 UTC Modified: 2011-03-02 05:15 UTC
From: daniel-marschall at viathinksoft dot de Assigned:
Status: Not a bug Package: Unknown/Other Function
PHP Version: 5.3.5 OS: Debian
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: daniel-marschall at viathinksoft dot de
New email:
PHP Version: OS:

 

 [2011-03-02 04:52 UTC] daniel-marschall at viathinksoft dot de
Description:
------------
If you access $_ENV or $_SERVER the indirect way, via ${'_SERVER'} you get an 
E_NOTICE message. Please see my test scripts.

Test script:
---------------
Producing the bug:

<?php
error_reporting(E_ALL | E_STRICT);
$x = '_SERVER';
print_r($$x); // Notice: Undefined variable: _SERVER
?>

Workaround with dummy function which "touches" the variable:

<?php
error_reporting(E_ALL | E_STRICT);

function dummy($dummy) {}
dummy($_SERVER); // "Touch"

$x = '_SERVER';
print_r($$x); // Everything is OK!
?>

Expected result:
----------------
I don't expect an message that $_SERVER or $_ENV are not valid variables. I kept 
searching for hours because I couldn't find any reason, why $_SERVER disappears, 
but is visible in phpinfo(). I do not know why I have to "touch" these super-
globals first, so that they get "active".


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-03-02 05:09 UTC] daniel-marschall at viathinksoft dot de
I have found something additional.

(1) You can also "touch" the variable with simple
<?php
$_SERVER;
?>

(2) You do not have to touch the Variable BEFORE you want to access it wit $$x. 
Actually, you just need to touch it ANYWHERE inside the script. Then, the PHP 
interpreter will "activate" $_SERVER.

This scripts will throw an notice:

<?php
error_reporting(E_ALL | E_STRICT);
$x = '_SERVER';
print_r($$x);
?>

These scripts will not throw an notice

<?php
error_reporting(E_ALL | E_STRICT);
print_r(${'_SERVER'});
?>

<?php
error_reporting(E_ALL | E_STRICT);
$x = '_SERVER';
print_r($$x);
$_SERVER; // Touch anywhere in the script to avoid error
?>

I believe the interpreter checks if $_SERVER or $_ENV is called somewhere in the 
script. If it is not called anywhere, it just don't load the variable.

In my opinion, this behavior is wrong. Since PHP cannot know what I do with 
variables like $$x, it cannot know if I am actually trying to access $_SERVER or 
$_ENV .

Solutions:

(1) Always "enable" _SERVER and _ENV

(2) When solving $$x , check if it is _SERVER or _ENV which is still disabled 
and then enable it. Then, access it.
 [2011-03-02 05:15 UTC] rasmus@php.net
-Status: Open +Status: Bogus
 [2011-03-02 05:15 UTC] rasmus@php.net
This is not a bug. It is a documented optimization feature. See 
http://php.net/manual/en/ini.core.php and look for the section on auto_globals_jit 
with the big pink warning which says, "Usage of SERVER and ENV variables is 
checked during compile time so using them through e.g. variable variables will not 
cause their initialization."
 [2011-03-02 06:40 UTC] daniel-marschall at viathinksoft dot de
Thank you for that information. I didn't knew this functionality. Now I know it.

But what do you think about an automatic detection of that issue? Then we would 
have one "pink box" less and one possible "trap" for the users.

If some internal PHP function would be:

function dereference_variable_variable(X) {
	if not existing (X) {
		throw E_NOTICE ...
	} else {
		return dereference(X);
	}
}

You could change it to:

function dereference_variable_variable(X) {
	if not existing (X) {
		if (X = '_SERVER') {
			register(_server);
			return dereference_variable_variable(X); // retry
		} else if (X = '_ENV') {
			register(_server);
			return dereference_variable_variable(X); // retry
		} else {
			throw E_NOTICE ...
		}
	} else {
		return dereference(X);
	}
}

Wouldn't that be an good idea? Then, users of variable variables have not to 
care about the JIT option, which can be different from server to server 
(important for OpenSource developers, when they don't know at which server 
configuration the script will run).
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 12:01:29 2024 UTC