php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #81171 &$GLOBALS not allowed anymore
Submitted: 2021-06-19 06:50 UTC Modified: 2021-06-19 07:20 UTC
From: herbert at groot dot jebbink dot nl Assigned:
Status: Wont fix Package: Arrays related
PHP Version: 8.1.0alpha1 OS: Linux
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: herbert at groot dot jebbink dot nl
New email:
PHP Version: OS:

 

 [2021-06-19 06:50 UTC] herbert at groot dot jebbink dot nl
Description:
------------
Below line gives in 8.1.0alpha1 the error "SHUTDOWN: Cannot acquire reference to $GLOBALS"

$pad_data [1] [1] = &$GLOBALS;

I did read below page and understand that changes are good in new releases, happy that PHP evolves.

https://wiki.php.net/rfc/restrict_globals_usage

however, it would be great if the error message only happens if the usage is not lookup but when it tries to change it.







Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-06-19 07:13 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2021-06-19 07:13 UTC] nikic@php.net
> however, it would be great if the error message only happens if the usage is not lookup but when it tries to change it.

Acquiring a reference allows further indirect changes, which cannot be tracked in a fine-grained manner. If you wrote $pad_data[1][1] = $GLOBALS, that would continue to work fine.

Closing this as the change is intentional and the impact on reference acquisition explicitly mentioned in the RFC.
 [2021-06-19 07:20 UTC] nikic@php.net
I'd be interested in what you're trying to do though, maybe I can suggest an alternative. The line you shared looks pretty odd to me, not really obvious why $GLOBALS is being assigned that way.
 [2021-06-19 08:47 UTC] herbert at groot dot jebbink dot nl
Thanks for the feedback, I understand it was intentional.

it's from an old framework from me, more then 10 years old, a template page in this framework looks like below:

{level1}
  {$varA}
  {level2}
    <li> {$varB}    
    {level3}
      <li> {$varC} - root is {$varA}
    {/level3}
  {/level2}
{/level1}

{level1} & {/level1} are not actually in the template, it's added automatically.

each level is repeated according to this $pad_data array, that means that level 1 will be repeaded 1 time and the level 1 variables are coming from $GLOBALS.

if the page specific code is:

$varA = 'aa1';

$level2 [1] ['varB'] = 'bb1';
$level2 [1] ['level3'] [1] ['varC'] = 'cc1';
$level2 [1] ['level3'] [2] ['varC'] = 'cc2';

$level2 [2] ['varB'] = 'bb2';
$level2 [2] ['level3'] [1] ['varC'] = 'cc3';
$level2 [2] ['level3'] [2] ['varC'] = 'cc4';

the result will be:

aa1
  <li> bb1
    <li> cc1 - root is aa1
    <li> cc2 - root is aa1
  <li> bb2
    <li> cc3 - root is aa1
    <li> cc4 - root is aa1

changing it to $pad_data [1] [1] = $GLOBALS does not work, when it is used later on, it needs the real values from that moment, but changing the code when it is used, did fix it.

global $pad_data, $pad_lvl, $pad_row;

for ( $i=$pad_lvl; $i; $i-- ) {
  $base = $pad_data [$i] [$pad_row[$i]];
  ...
}

new code

global $pad_data, $pad_lvl, $pad_row;

for ( $i=$pad_lvl; $i; $i-- ) {
  if ( $i == 1) 
    $base = $GLOBALS;
  else
    $base = $pad_data [$i] [$pad_row[$i]];
  ...
}

at the '...' code, it does only read $base, not changing it, also it is in a function, the $GLOBALS scope is not changed in this function. 

if I understand it correctly, no real memory is duplicated yet with $base = $GLOBALS, that would only happen if $base or $GLOBALS would be changed afterwards, and that will not happen in this function.
 [2021-06-20 04:42 UTC] herbert at groot dot jebbink dot nl
Shorter answer )

That line of code is used in a framework that is based on the concept of levels with rows inside a level.

In this concept it makes sence that level 1 has 1 row and that this row is $GLOBALS.

$pad_data [1] [1] = &$GLOBALS;

This way, when $pad_data is processed, it will automatically use $GLOBALS for row 1 of level 1.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 15:01:29 2024 UTC