php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76931 foreach by reference copies last array element from second-last
Submitted: 2018-09-24 21:20 UTC Modified: 2018-09-24 22:02 UTC
From: kellnerdenes at gmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 7.1.22 OS: Win64
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: kellnerdenes at gmail dot com
New email:
PHP Version: OS:

 

 [2018-09-24 21:20 UTC] kellnerdenes at gmail dot com
Description:
------------
When looping along an array twice, first by reference, then by just normal value, the last element gets affected (gets the value of the second-last). So while it should display "first second third fourth", it will give "first second third third" instead. Commenting any of the foreaches or changing their order makes the problem disappear.

I've seen similar reports but I think this one is clearly a bug while others seem to be unsure.

Test script:
---------------
$a = explode("\n","first\nsecond\nthird\nfourth");
foreach($a as &$x);
foreach($a as $x);
print_r($a);

Expected result:
----------------
Array
(
    [0] => first
    [1] => second
    [2] => third
    [3] => fourth
)

Actual result:
--------------
Array
(
    [0] => first
    [1] => second
    [2] => third
    [3] => third
)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-09-24 21:26 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2018-09-24 21:26 UTC] requinix@php.net
http://php.net/manual/en/control-structures.foreach.php
Big red warning. Should be hard to miss.
 [2018-09-24 21:48 UTC] spam2 at rhsoft dot net
man uset()
 [2018-09-24 21:50 UTC] spam2 at rhsoft dot net
to be clear:

foreach($a as &$x);
unset($x);
foreach($a as $x);

just don't use references until you understand the side-effects and are really sure you ebenfit from it which is motsly not true given the copy-on-write nature of PHP
 [2018-09-24 21:57 UTC] kellnerdenes at gmail dot com
Sure, you're right, it's somewhat expectable that the reference remains in $x from the first foreach; but the second foreach should create a new variable as $x, not reuse it. I can't see why it would keep it.
 [2018-09-24 22:02 UTC] requinix@php.net
> the second foreach should create a new variable as $x
A variable is a variable. When it is created it exists until it drops out of scope or something unset()s it. There is no such thing as creating a "new" variable with an existing name - it's merely assigning a new value to it.

If you literally wanted a new variable then you should literally use a new variable. Like $y.
 [2018-09-24 22:27 UTC] spam2 at rhsoft dot net
> second foreach should create a new variable as $x, not reuse it.
> I can't see why it would keep it.

and I don't see how PHP sould smell your intention and create magically a new variable - what if i want to re-use the referenced varible in the next step - again: don't use references until you fully understand them
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Thu Nov 15 04:01:25 2018 UTC