php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74020 Foreach-by-reference + assignment may recreate unexpected key references
Submitted: 2017-01-31 03:08 UTC Modified: 2017-01-31 08:57 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: icarpenter at leadid dot com Assigned:
Status: Verified Package: Scripting Engine problem
PHP Version: 7.0.15 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: icarpenter at leadid dot com
New email:
PHP Version: OS:

 

 [2017-01-31 03:08 UTC] icarpenter at leadid dot com
Description:
------------
After a foreach-by-reference, an array may create references to keys if you create a copy of the original variable (either directly or indirectly via foreach) and then on that new variable, create a copy of a key to another key. The original key in that variable will then become a reference to the same key in the original array.

In PHP 5.6 and 7.1, this can be avoided by either having the foreach run in a different scope, or unsetting the reference variable after the loop. PHP 7.0 exhibits this behavior regardless.

Test script:
---------------
https://3v4l.org/mHX7B (Triggers the bug in PHP 7.0)
https://3v4l.org/VLuhn (Triggers the bug in PHP 5.6, 7.0, and 7.1)

Expected result:
----------------
string(3) "foo"

Actual result:
--------------
string(3) "bar"

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-01-31 08:57 UTC] requinix@php.net
-Summary: Foreach-by-reference may create unexpected key references +Summary: Foreach-by-reference + assignment may recreate unexpected key references -Status: Open +Status: Verified -Package: Arrays related +Package: Scripting Engine problem
 [2017-01-31 08:57 UTC] requinix@php.net
Note that var_dump on the array will show references.

The first one looks like a bug as the reference was (supposedly) destroyed, however it comes back with the foo_copy=foo assignment. https://3v4l.org/DgJFP#v700

The second is not because $item is still a reference after the loop and when $mockCopy copies $mock it gets foo as a copy *of the reference*. https://3v4l.org/nrpE5 Adding unset($item) is the recommended solution. http://php.net/foreach
 [2017-01-31 15:28 UTC] icarpenter at leadid dot com
While I agree that unsetting the $item is a best practice, the docs only really say you'll run into issues if you happen to do something with the reference variable. Since I'm not doing that here, one wouldn't expect references to get created when copying the original variable. Maybe the docs can be updated to say that foreach by reference will not only leave a variable with a reference to the last key in the array hanging around, but also the original array may contain references as well unless you unset the variable.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC