Bug #76863 [NEW]: Creating array reference grants direct access to the property
| From: | tshumbeo at mailhouse dot biz | 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