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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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: Mon Oct 14 18:01:28 2024 UTC