rfc:on_demand_name_mangling
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
rfc:on_demand_name_mangling [2016/01/01 21:28] – created bishop | rfc:on_demand_name_mangling [2019/07/16 12:25] (current) – Settled on formal polyfill name, php_mangle_superglobal bishop | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: On-demand Name Mangling ====== | ====== PHP RFC: On-demand Name Mangling ====== | ||
- | * Version: 1 | + | * Version: 1.4 |
- | * Date: 2016-01-01 | + | * Created |
- | * Author: Bishop Bettini, bishop@php.net | + | * Updated Date: 2019-07-16 |
+ | * Author: Bishop Bettini | ||
* Status: Under Discussion | * Status: Under Discussion | ||
- | * First Published at: http:// | + | * First Published at: http:// |
===== Introduction ===== | ===== Introduction ===== | ||
- | PHP marshals external key-value pairs into super-globals by mangling some disallowed characters to underscores: | + | PHP marshals external key-value pairs into super-globals by [[https:// |
+ | |||
+ | * "'' | ||
+ | * If there is no "'' | ||
+ | * Other characters are left as is | ||
+ | |||
+ | As seen here, both for both '' | ||
< | < | ||
# the shell environment variable " | # the shell environment variable " | ||
- | $ / | + | $ / |
foo | foo | ||
# a " | # a " | ||
- | $ / | + | $ / |
foo | foo | ||
# same mangling rules for $_REQUEST | # same mangling rules for $_REQUEST | ||
- | # curiously "$" does not mangle, even though it's not a valid PHP variable name | + | # Note how $ is ignored |
$ cat mangle.phpt | $ cat mangle.phpt | ||
--TEST-- | --TEST-- | ||
Line 44: | Line 50: | ||
</ | </ | ||
- | Mangling has the undesirable consequence that //many// external variables may map to //one// PHP variable. For example, three separate HTML form elements named '' | + | Mangling has the undesirable consequence that //many// external variables may map to //one// PHP variable. For example, three separate HTML form elements named '' |
- | Automatic name mangling supported '' | + | Automatic name mangling supported '' |
- | + | ||
- | Yes, but not on import as before. Now, name mangling can be moved when extracting, which is when it's needed. | + | |
< | < | ||
--TEST-- | --TEST-- | ||
- | Name mangling logic moved to extract() | + | Name mangling logic removed from engine, placed in polyfill |
--GET-- | --GET-- | ||
- | a.b=dot& | + | a.b=dot& |
--FILE-- | --FILE-- | ||
<?php | <?php | ||
- | extract($_GET); | + | print_r(get_defined_vars()); |
+ | php_mangle_superglobals(); | ||
print_r(get_defined_vars()); | print_r(get_defined_vars()); | ||
?> | ?> | ||
Line 66: | Line 71: | ||
( | ( | ||
[a.b] => dot | [a.b] => dot | ||
+ | [a_b] => underscore | ||
[a$b] => dollar | [a$b] => dollar | ||
[a b] => space | [a b] => space | ||
[a[b] => bracket | [a[b] => bracket | ||
) | ) | ||
- | + | ) | |
- | [a_b] => bracket | + | Array |
+ | ( | ||
+ | | ||
+ | ( | ||
+ | | ||
+ | [a$b] => dollar | ||
+ | ) | ||
) | ) | ||
</ | </ | ||
- | In this new paradigm, all name mangling | + | In this new implementation, the engine no longer mangles marshaled superglobals at startup. |
+ | |||
+ | In the example above, an '' | ||
+ | |||
+ | Importantly, | ||
+ | |||
+ | The polyfill algorithm is simple: | ||
+ | |||
+ | * find all superglobal keys that violate the PHP unquoted variable name regex ((Unquoted variable names must match the 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. | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | This RFC proposes to phase out automatic name mangling, | + | This RFC proposes to remove |
- | * Next minor release (currently 7.1): | + | * Upon acceptance: |
- | * Emit an '' | + | * Update documentation |
+ | * Release a userland polyfill that implements the historic mangling behavior | ||
+ | * Polyfill shall be available via composer (but not PEAR) | ||
* Next major release (currently 8.0): | * Next major release (currently 8.0): | ||
- | * Remove all name mangling code in super-global | + | * Remove all name mangling code in super-global |
- | * Update '' | + | |
- | * If a prefix is given by any of the '' | + | |
- | * Honor '' | + | |
- | * Mangle the name such that any letter outside the documented regex '' | + | |
- | * Emit an '' | + | |
+ | ==== Discussion ==== | ||
+ | |||
+ | These questions were raised in the mailing list discussion. | ||
+ | |||
+ | === Should a notice be raised if the engine mangles a superglobal? | ||
+ | |||
+ | Before version 1.3, this RFC proposed raising an '' | ||
+ | |||
+ | > If I have a well behaved application that doesn’t rely on name mangling or have included the polyfill, how can I prevent a log message from being emitted when a user appends (unused) parameters to the query string that require mangling? | ||
+ | |||
+ | and Nikita Popov commented: | ||
+ | |||
+ | > Even if it's only a single deprecation warning instead of multiple, it's still a deprecation warning that I, as the application author, have absolutely no control over. For me, a deprecation warning indicates that there is some code I must change to make that warning *go away*. | ||
+ | > Sure, it's informative. But it's enough to be informative about this *once*, rather than every time a user makes an odd-ish request. | ||
+ | |||
+ | Given that (a) an application could get spammed by malicious users((The '' | ||
+ | |||
+ | === Should an INI configuration control mangling? === | ||
+ | |||
+ | Nikita Popov suggested (and Stanislav Malyshev seconded) a counter-proposal to use an INI setting: | ||
+ | |||
+ | > I would favor the introduction of a new ini setting. E.g. mangle_names=0 disables name mangling, while mangle_names=1 throws a deprecation warning on startup and enables name mangling. mangle_names=0 should be the default. That is essentially disable name mangling, but leave an escape hatch for those people who rely on it (for whatever reason). | ||
+ | |||
+ | An INI setting to disable mangling must be engine-wide (e.g., '' | ||
+ | |||
+ | It's still possible to provide an " | ||
+ | |||
+ | The polyfill approach is considered superior to the INI approach for three reasons: | ||
+ | |||
+ | * Userland can maintain BC independent of system INI settings (which they may not control) | ||
+ | * The engine is completely cleaned of all mangling behavior (which means less code to fuss over) | ||
+ | * No additional weight of configuration values (which is a complaint point for many) | ||
+ | |||
+ | === Should '' | ||
+ | |||
+ | Early versions of this proposal (< v1.2) proposed using '' | ||
+ | |||
+ | However, '' | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
- | This proposal introduces backward incompatible changes: any userland code relying on mangled names would have to change to using original variable names. | + | This proposal introduces backward incompatible changes: any userland code relying on mangled names would have to either (a) change to using original |
+ | |||
+ | The polyfill could be accomplished with code like: | ||
+ | |||
+ | <code php> | ||
+ | function php_mangle_name($name) { | ||
+ | $name = preg_replace('/ | ||
+ | return preg_replace('/ | ||
+ | } | ||
+ | function php_mangle_superglobals() { | ||
+ | if (version_compare(PHP_VERSION, | ||
+ | return; | ||
+ | } | ||
+ | foreach ($_ENV as $var => &$val) { | ||
+ | $mangled = php_mangle_name($var); | ||
+ | if ($mangled !== $var) { | ||
+ | $_ENV[$mangled] =& $val; | ||
+ | } | ||
+ | } | ||
+ | // similar loops for $_GET, $_POST | ||
+ | // similar logic for $_COOKIE and $_FILES | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | To reduce the burden on userland, this polyfill library could be made available via Composer: | ||
+ | |||
+ | < | ||
+ | $ composer require php/ | ||
+ | $ cat app/ | ||
+ | <?php | ||
+ | require __DIR__ . '/ | ||
+ | |||
+ | php_mangle_superglobals(); | ||
+ | |||
+ | // ... | ||
+ | </ | ||
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | PHP 7.1 (for notice of impending BC break) and PHP 8.0 (for actual implementation and corresponding BC break). | + | PHP 8.0. |
===== RFC Impact ===== | ===== RFC Impact ===== | ||
Line 115: | Line 207: | ||
===== Open Issues ===== | ===== Open Issues ===== | ||
- | None so far. | + | None. |
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
- | A simple yes/no voting option with a 2/3 majority required. | + | A simple yes/no voting option with a 2/3 majority required: " |
===== Patches and Tests ===== | ===== Patches and Tests ===== |
rfc/on_demand_name_mangling.1451683727.txt.gz · Last modified: 2017/09/22 13:28 (external edit)