php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #53780 Iterating twice over an array changes the array
Submitted: 2011-01-18 17:06 UTC Modified: 2011-01-18 18:56 UTC
From: daniel dot seif at castex dot de Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 5.3.5 OS: Ubuntu 11.04
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: daniel dot seif at castex dot de
New email:
PHP Version: OS:

 

 [2011-01-18 17:06 UTC] daniel dot seif at castex dot de
Description:
------------
When using foreach to iterate over an array using the reference (&$value) syntax, and using foreach a second time using the same variable name changes the original array by overwriting the array's last item with the second-last.

This is obviously wrong...


Hint: note the missing object's id #4 in the actual result

Test script:
---------------
// the example uses objects to show the object's id in the output, but this error also occurs works with scalars

class A {}

$c = array(new A(), new A(), new A(), new A());
$arr = $c; // to keep the reference

var_dump($arr);

foreach ($arr as &$value) {}
	
var_dump($arr);

// using the same variable name
foreach ($arr as $value) {}

var_dump($arr);

Expected result:
----------------
array(4) {
  [0]=>
  object(A)#1 (0) {
  }
  [1]=>
  object(A)#2 (0) {
  }
  [2]=>
  object(A)#3 (0) {
  }
  [3]=>
  object(A)#4 (0) {
  }
}
array(4) {
  [0]=>
  object(A)#1 (0) {
  }
  [1]=>
  object(A)#2 (0) {
  }
  [2]=>
  object(A)#3 (0) {
  }
  [3]=>
  object(A)#4 (0) {
  }
}
array(4) {
  [0]=>
  object(A)#1 (0) {
  }
  [1]=>
  object(A)#2 (0) {
  }
  [2]=>
  object(A)#3 (0) {
  }
  [3]=>
  object(A)#4 (0) {
  }
}


Actual result:
--------------
array(4) {
  [0]=>
  object(A)#1 (0) {
  }
  [1]=>
  object(A)#2 (0) {
  }
  [2]=>
  object(A)#3 (0) {
  }
  [3]=>
  object(A)#4 (0) {
  }
}
array(4) {
  [0]=>
  object(A)#1 (0) {
  }
  [1]=>
  object(A)#2 (0) {
  }
  [2]=>
  object(A)#3 (0) {
  }
  [3]=>
  &object(A)#4 (0) {
  }
}
array(4) {
  [0]=>
  object(A)#1 (0) {
  }
  [1]=>
  object(A)#2 (0) {
  }
  [2]=>
  object(A)#3 (0) {
  }
  [3]=>
  &object(A)#3 (0) {
  }
}


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-01-18 18:56 UTC] cataphract@php.net
-Status: Open +Status: Bogus
 [2011-01-18 18:56 UTC] cataphract@php.net
This is not a bug, it's an unfortunate consequence of the nonexistence of block-scoped variables in PHP.

When the first foreach loop ends, $value will still exist and the last element of $arr will be in the same reference set.

When the second foreach loop is running, $value will be written on each iteration; when that happens, the last element of the array, which is in the same reference set, will be changed too. From here, we can see that the last of such assignments to have any effect is the penultimate, since in the last assignment an element of the reference set is written onto another such element, so it has no effect.
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Sun May 31 09:00:01 2026 UTC