Bug #76863 [NEW]: Creating array reference grants direct access to the property

From: Date: Tue, 11 Sep 2018 19:14:16 +0000
Subject: Bug #76863 [NEW]: Creating array reference grants direct access to the property
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-216989@lists.php.net to get a copy of this message
From: tshumbeo at mailhouse dot biz Operating system: Linux and Windows PHP version: 7.2.9 Package: Scripting Engine problem Bug Type: Bug Bug description:Creating array reference grants direct access to the property Description: ------------ Tested on PHP 5.6.37 and 7.2.9, Windows and Linux, various configurations. See the test script. When (1) is present (assignment by reference) and (2) is missing (no unsetting), it appears that K->$a[0] itself becomes a reference (not $unusedVariable, which would be expected). When K->a() - a typical read accessor method - returns the array, modifying the array's member affects the K->$a. If (2) is present, then the $a[0] reference is removed and it's no more possible to change the K->$a by changing K->a() members. (1) | (2) | Result ----|-------|------- & | unset | no bug | unset | no bug | | no bug & | | bug! A practical consequence: I am unable to create a reference to the internal array's members (for use in other places) without opening doors to direct modification of the property which can happen inadvertently (this is how I stumbled upon it): function clean(array $ar) { foreach ($ar as &$ref) $ref = ...; return $ar; } clean($k->a()); Do note that clean() doesn't accept $a by reference, it simply uses it as a copy for returning in the result. However, due to the bug it in fact directly modifies $k's internal $a array! Test script: --------------- class K { private $a = ['a']; function a() { return $this->a; } function f($f) { // (1) $unusedVariable = &$this->a[0]; // (2) //unset($unusedVariable); $f(); } } $k = new K; $k->f(function () use ($k) { foreach ($k->a() as &$ref) { $ref = 123; } }); // Expected result: string 'a'. // Actual result: int 123. var_dump($k->a()); Expected result: ---------------- Creating a reference *to* an array member (1) should *not* turn that member into a reference (to itself?). Actual result: -------------- Creating a reference turns that member into a sticky reference that isn't removed by array cloning functions like array_values(), array_merge(), unset(), etc. and can be removed only by unsetting (2) the referencing variable (even if it's out of scope the reference remains). -- Edit bug report at https://bugs.php.net/bug.php?id=76863&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=76863&r=trysnapshot54 Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=76863&r=trysnapshot55 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=76863&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=76863&r=fixed Fixed in release: https://bugs.php.net/fix.php?id=76863&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=76863&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=76863&r=needscript Try newer version: https://bugs.php.net/fix.php?id=76863&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=76863&r=support Expected behavior: https://bugs.php.net/fix.php?id=76863&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=76863&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=76863&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=76863&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=76863&r=php4 Daylight Savings: https://bugs.php.net/fix.php?id=76863&r=dst IIS Stability: https://bugs.php.net/fix.php?id=76863&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=76863&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=76863&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=76863&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=76863&r=mysqlcfg

« previous php.bugs (#216989) next »