PHP marshals external key-value pairs into super-globals by mangling some disallowed characters to underscores:

“ . ” and “ ” become an “ _ ”

If there is no “ ] ”, then the first “ [ ” also becomes an “ _ ” -- all other left brackets remain intact

Other characters are left as is

As seen here, both for both $_ENV and $_GET :

# the shell environment variable "a.b" becomes "a_b" inside $_ENV $ /usr/bin/env "a.b=foo" php -r 'echo $_ENV["a_b"];' foo # a "[" also mangles to an underscore $ /usr/bin/env "a[b=foo" php -r 'echo $_ENV["a_b"];' foo # same mangling rules for $_REQUEST # Note how $ is ignored $ cat mangle.phpt --TEST-- How does $_REQUEST handle HTML form variables with unusual names? --GET-- a.b=dot&a$b=dollar&a%20b=space&a[b=bracket --FILE-- <?php print_r($_GET); ?> --EXPECTF-- Array ( [a_b] => bracket [a$b] => dollar ) $ pear run-tests --cgi=/usr/bin/php-cgi mangle.phpt Running 1 tests PASS How does $_REQUEST handle HTML form variables with unusual names?[mangle.phpt] TOTAL TIME: 00:00 1 PASSED TESTS 0 SKIPPED TESTS

Mangling has the undesirable consequence that many external variables may map to one PHP variable. For example, three separate HTML form elements named a.b , a_b and a[b will all resolve to a_b in the corresponding super-global, with the value from a[b winning (because it was last). This leads to user confusion and userland work arounds, not to mention bug reports: #34882 and #42055 for example.

Automatic name mangling supported register_globals and its kin like import_request_variables() , but those features ended in August 2014. Name mangling isn't required for super-global marshaling, because the associative array nature of super-globals can accommodate any string variable name. So do we need automatic name mangling? Consider this hypothetical new test:

--TEST-- Name mangling logic removed from engine, placed in polyfill --GET-- a.b=dot&a_b=underscore&a$b=dollar&a%20b=space&a[b=bracket --FILE-- <?php print_r(get_defined_vars()); php_mangle_superglobals(); print_r(get_defined_vars()); ?> --EXPECTF-- Array ( [_GET] => Array ( [a.b] => dot [a_b] => underscore [a$b] => dollar [a b] => space [a[b] => bracket ) ) Array ( [_GET] => Array ( [a_b] => bracket [a$b] => dollar ) )

In this new implementation, the engine no longer mangles marshaled superglobals at startup. Instead, the ability to mangle names has moved to an optional, userland-provided polyfill function php_mangle_superglobals() .

In the example above, an a_b key was externally supplied. The call to php_mangle_superglobals clobbered the original value of a_b with the value of the last seen mangle-equivalent key ( a[b ).

Importantly, the user made this mangling happen: the engine did not do it automatically.

The polyfill algorithm is simple:

1) find all superglobal keys that violate the PHP unquoted variable name regex

for each, create a new mangled key linked to the corresponding value

Applications requiring name mangling may call the polyfill during their bootstrap phase to emulate prior engine behavior.