Skip to content

Language: $GLOBALS = [] compiles — Zend can only be modified using $GLOBALS[$name] syntax (Zend/zend_compile.c) #32229

Description

@PurHur

Category

language · php-src-strict · compile-time fatal · $GLOBALS (sibling of #15627)

Problem

Wholesale writes to the $GLOBALS variable are accepted (rc=0). Zend 8.1+ is a compile-time fatal:

$GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax

&$GLOBALS is already a compile fatal (#15627, Cannot acquire reference to $GLOBALS). Indexed $GLOBALS['x'] = 1 is valid on both sides (control). The remaining holes are assign / assign-op / unset of the $GLOBALS variable itself.

Verified 2026-08-18 @ 3633ba3bb9 vs Zend 8.2.32.

Repro Zend 8.2.32 VM / JIT
$GLOBALS = []; Fatal $GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax accepted (rc=0)
$GLOBALS += ['x' => 1]; same fatal accepted (rc=0)
unset($GLOBALS); same fatal accepted (rc=0)
$a = &$GLOBALS; (control, #15627) Fatal Cannot acquire reference to $GLOBALS same (match)
$GLOBALS['x'] = 1; (control) rc=0 rc=0

php-src reference

  • php/php-src Zend/zend_compile.c — zend_compile_assign() / zend_compile_assign_op() / zend_compile_unset(); bare $GLOBALS as the write target → $GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax
  • PHP 8.1 “Restrict $GLOBALS” RFC; indexed $GLOBALS[$name] remains the only legal write

PHP implementation target

  • lib/Compiler.php — extend the existing #15627 rejectGlobalsReferenceAcquisition() family: reject assign / += / unset when the target’s base name is GLOBALS (not $GLOBALS['k'] dim writes)
  • Reuse throwCompileError with the Zend sentence above
  • Same compile path for JIT/AOT; no new runtime/*.c logic

Repro

./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/maintainer_gap_globals_assign.php 2>&1 | head -5'
./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/maintainer_gap_globals_plus_assign.php 2>&1 | head -5'
./script/docker-exec.sh -- bash -lc 'php bin/vm.php test/repro/maintainer_gap_unset_globals.php 2>&1 | head -5'
./script/docker-exec.sh -- bash -lc 'php bin/jit.php test/repro/maintainer_gap_globals_assign.php 2>&1 | head -5'
<?php
$GLOBALS = [];
echo "accepted\n";

Done when

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:compilerCompiler / CFG / JITarea:vmVirtual machinebugSomething isn't workingimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions