Bug #29992 [Com]: foreach by reference corrupts the array

From: Date: Wed, 13 Jul 2011 10:37:58 +0000
Subject: Bug #29992 [Com]: foreach by reference corrupts the array
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-161857@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=29992&edit=1

 ID:                 29992
 Comment by:         martijn at twotribes dot com
 Reported by:        fletch at pobox dot com
 Summary:            foreach by reference corrupts the array
 Status:             Bogus
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   linux
 PHP Version:        5.0.1
 Block user comment: N
 Private report:     N

 New Comment:

Can someone please promote this "bogus" status to an actual bug? It completely baffles me
why something so obviously wrong, has been present in PHP for almost 7(!) years. Come on guys, fix
this!


Previous Comments:
------------------------------------------------------------------------
[2011-07-01 06:41:47] daniel at milde dot cz

I agree with Looris. This behaviour is dangerous and no one expects it.

I suggest unsetting the variable BEFORE each loop. This should cause no harm.

------------------------------------------------------------------------
[2010-11-27 14:59:24] johannes@php.net

I explained this with some pictures in my blog: http://schlueters.de/blog/archives/141-References-and-foreach.html

And no, unsetting after the loop is no option as it is inconsistent with other loops and there are
valid reasons for keeping it after the loop. Something along the lines of

foreach ($array as &$item) {
    if ($item == "foo") {
        break;
    }
}

$item = "bar";

------------------------------------------------------------------------
[2010-11-27 10:28:58] tarama at hotmail dot com

I highly agree with looris. I had to patch each use of hundreds of foreach loops in my code due to
this weird behaviour. The unset() tips at the end of each loop does the job, but from my point of
view it's really not logical. It caused really hard to find bugs in my code and I prefer to not
imagine how many PHP scritps are running on the web with the same "bug" silently breaking
things.

------------------------------------------------------------------------
[2010-05-24 19:20:22] looris at gmail dot com

This *IS* a bug, since no one would EVER expect this kind of behaviour.
And no one "might use this for some weird reason", believe me.

"foreach" means "do stuff FOR EACH element of an array".
It does not mean, to any sane person, "do stuff for each element of an array except the last
one, and twice for the one before the last one".

Your stubbornness in stating this is intentional is quite frightening.

------------------------------------------------------------------------
[2006-08-07 14:18:11] kouber@php.net

Although there's a user note in the manual, still this problem is not described in the
documentation itself.

Anyway, I believe the behaviour of foreach in this case is extremely dangerous. Imagine there's
such a "referential" loop in a library which is included by some other scripts and it
operates on $_SESSION or some other important array. Now any foreach in the other scripts might
corrupt the base array without even knowing it - just because the name of the "value"
variable is the same.

The main purpose of foreach itself is (as the name implies) to do something "for each"
element of the array, i.e. to provide an easier way to traverse an array than the other loop
constructs and not to touch other variables or references that are still pointing somewhere, unless
it's done implicitly in the body of the loop.

IMHO, foreach has to clear the variables used for key-value pairs, i.e. to unset the reference
before proceeding, just like it resets the array pointer. Otherwise we have to put a big red note in
the manual to always unset variables after using the referential syntax or to use
$long_descriptive_names_for_references, which is a little unreasonable in the current context.

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=29992


-- 
Edit this bug report at https://bugs.php.net/bug.php?id=29992&edit=1


Thread (43 messages)

« previous php.bugs (#161857) next »