New tests for foreach loops. These were written by another member of the Projectzero team.

This commit is contained in:
Robert Nicholson 2009-06-07 21:01:51 +00:00
parent 77693a80b7
commit d46dab70e8
17 changed files with 2941 additions and 0 deletions

View File

@ -0,0 +1,64 @@
--TEST--
Foreach loop tests - basic loop with just value and key => value.
--FILE--
<?php
$a = array("a","b","c");
foreach ($a as $v) {
var_dump($v);
}
foreach ($a as $k => $v) {
var_dump($k, $v);
}
//check key and value after the loop.
var_dump($k, $v);
echo "\n";
//Dynamic array
foreach (array("d","e","f") as $v) {
var_dump($v);
}
foreach (array("d","e","f") as $k => $v) {
var_dump($k, $v);
}
//check key and value after the loop.
var_dump($k, $v);
echo "\n";
//Ensure counter is advanced during loop
$a=array("a","b","c");
foreach ($a as $v);
var_dump(current($a));
$a=array("a","b","c");
foreach ($a as &$v);
var_dump(current($a));
?>
--EXPECT--
unicode(1) "a"
unicode(1) "b"
unicode(1) "c"
int(0)
unicode(1) "a"
int(1)
unicode(1) "b"
int(2)
unicode(1) "c"
int(2)
unicode(1) "c"
unicode(1) "d"
unicode(1) "e"
unicode(1) "f"
int(0)
unicode(1) "d"
int(1)
unicode(1) "e"
int(2)
unicode(1) "f"
int(2)
unicode(1) "f"
bool(false)
bool(false)

View File

@ -0,0 +1,173 @@
--TEST--
Foreach loop tests - modifying the array during the loop.
--FILE--
<?php
echo "\nDirectly changing array values.\n";
$a = array("original.1","original.2","original.3");
foreach ($a as $k=>$v) {
$a[$k]="changed.$k";
var_dump($v);
}
var_dump($a);
echo "\nModifying the foreach \$value.\n";
$a = array("original.1","original.2","original.3");
foreach ($a as $k=>$v) {
$v="changed.$k";
}
var_dump($a);
echo "\nModifying the foreach &\$value.\n";
$a = array("original.1","original.2","original.3");
foreach ($a as $k=>&$v) {
$v="changed.$k";
}
var_dump($a);
echo "\nPushing elements onto an unreferenced array.\n";
$a = array("original.1","original.2","original.3");
$counter=0;
foreach ($a as $v) {
array_push($a, "new.$counter");
//avoid infinite loop if test is failing
if ($counter++>10) {
echo "Loop detected\n";
break;
}
}
var_dump($a);
echo "\nPushing elements onto an unreferenced array, using &\$value.\n";
$a = array("original.1","original.2","original.3");
$counter=0;
foreach ($a as &$v) {
array_push($a, "new.$counter");
//avoid infinite loop if test is failing
if ($counter++>10) {
echo "Loop detected\n";
break;
}
}
var_dump($a);
echo "\nPopping elements off an unreferenced array.\n";
$a = array("original.1","original.2","original.3");
foreach ($a as $v) {
array_pop($a);
var_dump($v);
}
var_dump($a);
echo "\nPopping elements off an unreferenced array, using &\$value.\n";
$a = array("original.1","original.2","original.3");
foreach ($a as &$v) {
array_pop($a);
var_dump($v);
}
var_dump($a);
?>
--EXPECT--
Directly changing array values.
unicode(10) "original.1"
unicode(10) "original.2"
unicode(10) "original.3"
array(3) {
[0]=>
unicode(9) "changed.0"
[1]=>
unicode(9) "changed.1"
[2]=>
unicode(9) "changed.2"
}
Modifying the foreach $value.
array(3) {
[0]=>
unicode(10) "original.1"
[1]=>
unicode(10) "original.2"
[2]=>
unicode(10) "original.3"
}
Modifying the foreach &$value.
array(3) {
[0]=>
unicode(9) "changed.0"
[1]=>
unicode(9) "changed.1"
[2]=>
&unicode(9) "changed.2"
}
Pushing elements onto an unreferenced array.
array(6) {
[0]=>
unicode(10) "original.1"
[1]=>
unicode(10) "original.2"
[2]=>
unicode(10) "original.3"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.2"
}
Pushing elements onto an unreferenced array, using &$value.
Loop detected
array(15) {
[0]=>
unicode(10) "original.1"
[1]=>
unicode(10) "original.2"
[2]=>
unicode(10) "original.3"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.2"
[6]=>
unicode(5) "new.3"
[7]=>
unicode(5) "new.4"
[8]=>
unicode(5) "new.5"
[9]=>
unicode(5) "new.6"
[10]=>
unicode(5) "new.7"
[11]=>
&unicode(5) "new.8"
[12]=>
unicode(5) "new.9"
[13]=>
unicode(6) "new.10"
[14]=>
unicode(6) "new.11"
}
Popping elements off an unreferenced array.
unicode(10) "original.1"
unicode(10) "original.2"
unicode(10) "original.3"
array(0) {
}
Popping elements off an unreferenced array, using &$value.
unicode(10) "original.1"
unicode(10) "original.2"
array(1) {
[0]=>
unicode(10) "original.1"
}

View File

@ -0,0 +1,46 @@
--TEST--
Foreach loop tests - error case: not an array.
--FILE--
<?php
echo "\nNot an array.\n";
$a = TRUE;
foreach ($a as $v) {
var_dump($v);
}
$a = null;
foreach ($a as $v) {
var_dump($v);
}
$a = 1;
foreach ($a as $v) {
var_dump($v);
}
$a = 1.5;
foreach ($a as $v) {
var_dump($v);
}
$a = "hello";
foreach ($a as $v) {
var_dump($v);
}
echo "done.\n";
?>
--EXPECTF--
Not an array.
Warning: Invalid argument supplied for foreach() in %s on line 4
Warning: Invalid argument supplied for foreach() in %s on line 9
Warning: Invalid argument supplied for foreach() in %s on line 14
Warning: Invalid argument supplied for foreach() in %s on line 19
Warning: Invalid argument supplied for foreach() in %s on line 24
done.

View File

@ -0,0 +1,76 @@
--TEST--
Foreach loop tests - using an array element as the $value
--FILE--
<?php
$a=array("a", "b", "c");
$v=array();
foreach($a as $v[0]) {
var_dump($v);
}
var_dump($a);
var_dump($v);
echo "\n";
$a=array("a", "b", "c");
$v=array();
foreach($a as $k=>$v[0]) {
var_dump($k, $v);
}
var_dump($a);
var_dump($k, $v);
?>
--EXPECT--
array(1) {
[0]=>
unicode(1) "a"
}
array(1) {
[0]=>
unicode(1) "b"
}
array(1) {
[0]=>
unicode(1) "c"
}
array(3) {
[0]=>
unicode(1) "a"
[1]=>
unicode(1) "b"
[2]=>
unicode(1) "c"
}
array(1) {
[0]=>
unicode(1) "c"
}
int(0)
array(1) {
[0]=>
unicode(1) "a"
}
int(1)
array(1) {
[0]=>
unicode(1) "b"
}
int(2)
array(1) {
[0]=>
unicode(1) "c"
}
array(3) {
[0]=>
unicode(1) "a"
[1]=>
unicode(1) "b"
[2]=>
unicode(1) "c"
}
int(2)
array(1) {
[0]=>
unicode(1) "c"
}

View File

@ -0,0 +1,23 @@
--TEST--
Foreach loop tests - modifying the array during the loop: special case. Behaviour is good since php 5.2.2.
--FILE--
<?php
$a = array("original.0","original.1","original.2");
foreach ($a as $k=>&$v){
$a[$k] = "changed.$k";
echo "After changing \$a directly, \$v@$k is: $v\n";
}
//--- Expected output:
//After changing $a directly, $v@0 is: changed.0
//After changing $a directly, $v@1 is: changed.1
//After changing $a directly, $v@2 is: changed.2
//--- Actual output from php.net before 5.2.2:
//After changing $a directly, $v@0 is: changed.0
//After changing $a directly, $v@1 is: original.1
//After changing $a directly, $v@2 is: original.2
?>
--EXPECT--
After changing $a directly, $v@0 is: changed.0
After changing $a directly, $v@1 is: changed.1
After changing $a directly, $v@2 is: changed.2

View File

@ -0,0 +1,11 @@
--TEST--
Foreach loop tests - error case: key is a reference.
--FILE--
<?php
$a = array("a","b","c");
foreach ($a as &$k=>$v) {
var_dump($v);
}
?>
--EXPECTF--
Fatal error: Key element cannot be a reference in %s on line 3

View File

@ -0,0 +1,11 @@
--TEST--
Foreach loop tests - error case: reference to constant array.
--FILE--
<?php
echo "\nReference to constant array\n";
foreach (array(1,2) as &$v) {
var_dump($v);
}
?>
--EXPECTF--
Parse error: %s on line 3

View File

@ -0,0 +1,10 @@
--TEST--
Foreach loop tests - error case: reference to constant array, with key.
--FILE--
<?php
foreach (array(1,2) as $k=>&$v) {
var_dump($v);
}
?>
--EXPECTF--
Fatal error: Cannot create references to elements of a temporary array expression in %s on line 2

View File

@ -0,0 +1,82 @@
--TEST--
Foreach loop tests - foreach operates on the original array if the array is referenced outside the loop.
--FILE--
<?php
// From php.net/foreach:
// "Unless the array is referenced, foreach operates on a copy of the specified array."
echo "\nRemove elements from a referenced array during loop\n";
$refedArray=array("original.0", "original.1", "original.2");
$ref=&$refedArray;
foreach ($refedArray as $k=>$v1) {
array_pop($refedArray);
echo "key: $k; value: $v1\n";
}
echo "\nRemove elements from a referenced array during loop, using &\$value\n";
$refedArray=array("original.0", "original.1", "original.2");
$ref=&$refedArray;
foreach ($refedArray as $k=>&$v2) {
array_pop($refedArray);
echo "key: $k; value: $v2\n";
}
echo "\nAdd elements to a referenced array during loop\n";
$refedArray=array("original.0", "original.1", "original.2");
$ref=&$refedArray;
$count=0;
foreach ($refedArray as $k=>$v3) {
array_push($refedArray, "new.$k");
echo "key: $k; value: $v3\n";
if ($count++>5) {
echo "Loop detected, as expected.\n";
break;
}
}
echo "\nAdd elements to a referenced array during loop, using &\$value\n";
$refedArray=array("original.0", "original.1", "original.2");
$ref=&$refedArray;
$count=0;
foreach ($refedArray as $k=>&$v4) {
array_push($refedArray, "new.$k");
echo "key: $k; value: $v4\n";
if ($count++>5) {
echo "Loop detected, as expected.\n";
break;
}
}
?>
--EXPECT--
Remove elements from a referenced array during loop
key: 0; value: original.0
key: 1; value: original.1
Remove elements from a referenced array during loop, using &$value
key: 0; value: original.0
key: 1; value: original.1
Add elements to a referenced array during loop
key: 0; value: original.0
key: 1; value: original.1
key: 2; value: original.2
key: 3; value: new.0
key: 4; value: new.1
key: 5; value: new.2
key: 6; value: new.3
Loop detected, as expected.
Add elements to a referenced array during loop, using &$value
key: 0; value: original.0
key: 1; value: original.1
key: 2; value: original.2
key: 3; value: new.0
key: 4; value: new.1
key: 5; value: new.2
key: 6; value: new.3
Loop detected, as expected.

View File

@ -0,0 +1,40 @@
--TEST--
This test illustrates the impact of invoking destructors when refcount is decremented to 0 on foreach.
It will pass only if the 'contentious code' in PHPValue.decReferences() is enabled.
--FILE--
<?php
$a = array(1,2,3);
$container = array(&$a);
// From php.net:
// "Unless the array is referenced, foreach operates on a copy of
// the specified array and not the array itself."
// At this point, the array $a is referenced.
// The following line ensures $a is no longer references as a consequence
// of running the 'destructor' on $container.
$container = null;
// At this point the array $a is no longer referenced, so foreach should operate on a copy of the array.
// However, P8 does not invoke 'destructors' when refcount is decremented to 0.
// Consequently, $a thinks it is still referenced, and foreach will operate on the array itself.
// This provokes a difference in behaviour when changing the number of elements in the array while
// iterating over it.
$i=0;
foreach ($a as $v) {
array_push($a, 'new');
var_dump($v);
if (++$i>10) {
echo "Infinite loop detected\n";
break;
}
}
?>
--EXPECTF--
int(1)
int(2)
int(3)

View File

@ -0,0 +1,34 @@
--TEST--
Changing from an interable type to a non iterable type during the iteration
--FILE--
<?php
echo "\nChange from array to non iterable:\n";
$a = array(1,2,3);
$b=&$a;
foreach ($a as $v) {
var_dump($v);
$b=1;
}
echo "\nChange from object to non iterable:\n";
$a = new stdClass;
$a->a=1;
$a->b=2;
$b=&$a;
foreach ($a as $v) {
var_dump($v);
$b='x';
}
?>
--EXPECTF--
Change from array to non iterable:
int(1)
Warning: Invalid argument supplied for foreach() in %s on line 5
Change from object to non iterable:
int(1)
Warning: Invalid argument supplied for foreach() in %s on line 15

View File

@ -0,0 +1,494 @@
--TEST--
Directly modifying an unreferenced array when foreach'ing over it.
--FILE--
<?php
define('MAX_LOOPS',5);
function withRefValue($elements, $transform) {
echo "\n---( Array with $elements element(s): )---\n";
//Build array:
for ($i=0; $i<$elements; $i++) {
$a[] = "v.$i";
}
$counter=0;
echo "--> State of array before loop:\n";
var_dump($a);
echo "--> Do loop:\n";
foreach ($a as $k=>$v) {
echo " iteration $counter: \$k=$k; \$v=$v\n";
eval($transform);
$counter++;
if ($counter>MAX_LOOPS) {
echo " ** Stuck in a loop! **\n";
break;
}
}
echo "--> State of array after loop:\n";
var_dump($a);
}
echo "\nPopping elements off end of an unreferenced array";
$transform = 'array_pop($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nShift elements off start of an unreferenced array";
$transform = 'array_shift($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nRemove current element of an unreferenced array";
$transform = 'unset($a[$k]);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the end of an unreferenced array";
$transform = 'array_push($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the start of an unreferenced array";
$transform = 'array_unshift($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
?>
--EXPECTF--
Popping elements off end of an unreferenced array
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(0) {
}
Shift elements off start of an unreferenced array
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(0) {
}
Remove current element of an unreferenced array
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(0) {
}
Adding elements to the end of an unreferenced array
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(5) "new.0"
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(5) "new.0"
[3]=>
unicode(5) "new.1"
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(6) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.2"
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(8) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
[4]=>
unicode(5) "new.0"
[5]=>
unicode(5) "new.1"
[6]=>
unicode(5) "new.2"
[7]=>
unicode(5) "new.3"
}
Adding elements to the start of an unreferenced array
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
unicode(5) "new.0"
[1]=>
unicode(3) "v.0"
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(4) {
[0]=>
unicode(5) "new.1"
[1]=>
unicode(5) "new.0"
[2]=>
unicode(3) "v.0"
[3]=>
unicode(3) "v.1"
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(6) {
[0]=>
unicode(5) "new.2"
[1]=>
unicode(5) "new.1"
[2]=>
unicode(5) "new.0"
[3]=>
unicode(3) "v.0"
[4]=>
unicode(3) "v.1"
[5]=>
unicode(3) "v.2"
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(8) {
[0]=>
unicode(5) "new.3"
[1]=>
unicode(5) "new.2"
[2]=>
unicode(5) "new.1"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(3) "v.0"
[5]=>
unicode(3) "v.1"
[6]=>
unicode(3) "v.2"
[7]=>
unicode(3) "v.3"
}

View File

@ -0,0 +1,555 @@
--TEST--
Directly modifying an unreferenced array when foreach'ing over it while using &$value syntax.
--FILE--
<?php
define('MAX_LOOPS',5);
function withRefValue($elements, $transform) {
echo "\n---( Array with $elements element(s): )---\n";
//Build array:
for ($i=0; $i<$elements; $i++) {
$a[] = "v.$i";
}
$counter=0;
echo "--> State of array before loop:\n";
var_dump($a);
echo "--> Do loop:\n";
foreach ($a as $k=>&$v) {
echo " iteration $counter: \$k=$k; \$v=$v\n";
eval($transform);
$counter++;
if ($counter>MAX_LOOPS) {
echo " ** Stuck in a loop! **\n";
break;
}
}
echo "--> State of array after loop:\n";
var_dump($a);
}
echo "\nPopping elements off end of an unreferenced array, using &\$value.";
$transform = 'array_pop($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nShift elements off start of an unreferenced array, using &\$value.";
$transform = 'array_shift($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nRemove current element of an unreferenced array, using &\$value.";
$transform = 'unset($a[$k]);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the end of an unreferenced array, using &\$value.";
$transform = 'array_push($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the start of an unreferenced array, using &\$value.";
$transform = 'array_unshift($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
?>
--EXPECTF--
Popping elements off end of an unreferenced array, using &$value.
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=0; $v=v.0
iteration 3: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
Shift elements off start of an unreferenced array, using &$value.
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
iteration 2: $k=0; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
iteration 2: $k=0; $v=v.2
iteration 3: $k=0; $v=v.3
--> State of array after loop:
array(0) {
}
Remove current element of an unreferenced array, using &$value.
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(0) {
}
Adding elements to the end of an unreferenced array, using &$value.
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
&unicode(3) "v.0"
[1]=>
unicode(5) "new.0"
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=new.0
iteration 3: $k=3; $v=new.1
iteration 4: $k=4; $v=new.2
iteration 5: $k=5; $v=new.3
** Stuck in a loop! **
--> State of array after loop:
array(8) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(5) "new.0"
[3]=>
unicode(5) "new.1"
[4]=>
unicode(5) "new.2"
[5]=>
&unicode(5) "new.3"
[6]=>
unicode(5) "new.4"
[7]=>
unicode(5) "new.5"
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=new.0
iteration 4: $k=4; $v=new.1
iteration 5: $k=5; $v=new.2
** Stuck in a loop! **
--> State of array after loop:
array(9) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(5) "new.1"
[5]=>
&unicode(5) "new.2"
[6]=>
unicode(5) "new.3"
[7]=>
unicode(5) "new.4"
[8]=>
unicode(5) "new.5"
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
iteration 4: $k=4; $v=new.0
iteration 5: $k=5; $v=new.1
** Stuck in a loop! **
--> State of array after loop:
array(10) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
[4]=>
unicode(5) "new.0"
[5]=>
&unicode(5) "new.1"
[6]=>
unicode(5) "new.2"
[7]=>
unicode(5) "new.3"
[8]=>
unicode(5) "new.4"
[9]=>
unicode(5) "new.5"
}
Adding elements to the start of an unreferenced array, using &$value.
---( Array with 1 element(s): )---
--> State of array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
unicode(5) "new.0"
[1]=>
&unicode(3) "v.0"
}
---( Array with 2 element(s): )---
--> State of array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(8) {
[0]=>
unicode(5) "new.5"
[1]=>
&unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
}
---( Array with 3 element(s): )---
--> State of array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(9) {
[0]=>
unicode(5) "new.5"
[1]=>
&unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
[8]=>
unicode(3) "v.2"
}
---( Array with 4 element(s): )---
--> State of array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(10) {
[0]=>
unicode(5) "new.5"
[1]=>
&unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
[8]=>
unicode(3) "v.2"
[9]=>
unicode(3) "v.3"
}

View File

@ -0,0 +1,556 @@
--TEST--
Directly modifying a REFERENCED array when foreach'ing over it.
--FILE--
<?php
define('MAX_LOOPS',5);
function withRefValue($elements, $transform) {
echo "\n---( Array with $elements element(s): )---\n";
//Build array:
for ($i=0; $i<$elements; $i++) {
$a[] = "v.$i";
}
$counter=0;
$ref = &$a;
echo "--> State of referenced array before loop:\n";
var_dump($a);
echo "--> Do loop:\n";
foreach ($a as $k=>$v) {
echo " iteration $counter: \$k=$k; \$v=$v\n";
eval($transform);
$counter++;
if ($counter>MAX_LOOPS) {
echo " ** Stuck in a loop! **\n";
break;
}
}
echo "--> State of array after loop:\n";
var_dump($a);
}
echo "\nPopping elements off end of a referenced array";
$transform = 'array_pop($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nShift elements off start of a referenced array";
$transform = 'array_shift($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nRemove current element of a referenced array";
$transform = 'unset($a[$k]);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the end of a referenced array";
$transform = 'array_push($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the start of a referenced array";
$transform = 'array_unshift($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
?>
--EXPECTF--
Popping elements off end of a referenced array
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=0; $v=v.0
iteration 3: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
Shift elements off start of a referenced array
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
iteration 2: $k=0; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
iteration 2: $k=0; $v=v.2
iteration 3: $k=0; $v=v.3
--> State of array after loop:
array(0) {
}
Remove current element of a referenced array
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(0) {
}
Adding elements to the end of a referenced array
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(5) "new.0"
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=new.0
iteration 3: $k=3; $v=new.1
iteration 4: $k=4; $v=new.2
iteration 5: $k=5; $v=new.3
** Stuck in a loop! **
--> State of array after loop:
array(8) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(5) "new.0"
[3]=>
unicode(5) "new.1"
[4]=>
unicode(5) "new.2"
[5]=>
unicode(5) "new.3"
[6]=>
unicode(5) "new.4"
[7]=>
unicode(5) "new.5"
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=new.0
iteration 4: $k=4; $v=new.1
iteration 5: $k=5; $v=new.2
** Stuck in a loop! **
--> State of array after loop:
array(9) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.2"
[6]=>
unicode(5) "new.3"
[7]=>
unicode(5) "new.4"
[8]=>
unicode(5) "new.5"
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
iteration 4: $k=4; $v=new.0
iteration 5: $k=5; $v=new.1
** Stuck in a loop! **
--> State of array after loop:
array(10) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
[4]=>
unicode(5) "new.0"
[5]=>
unicode(5) "new.1"
[6]=>
unicode(5) "new.2"
[7]=>
unicode(5) "new.3"
[8]=>
unicode(5) "new.4"
[9]=>
unicode(5) "new.5"
}
Adding elements to the start of a referenced array
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
unicode(5) "new.0"
[1]=>
unicode(3) "v.0"
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(8) {
[0]=>
unicode(5) "new.5"
[1]=>
unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(9) {
[0]=>
unicode(5) "new.5"
[1]=>
unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
[8]=>
unicode(3) "v.2"
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(10) {
[0]=>
unicode(5) "new.5"
[1]=>
unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
[8]=>
unicode(3) "v.2"
[9]=>
unicode(3) "v.3"
}

View File

@ -0,0 +1,557 @@
--TEST--
Directly modifying a REFERENCED array when foreach'ing over it while using &$value syntax.
--FILE--
<?php
define('MAX_LOOPS',5);
function withRefValue($elements, $transform) {
echo "\n---( Array with $elements element(s): )---\n";
//Build array:
for ($i=0; $i<$elements; $i++) {
$a[] = "v.$i";
}
$counter=0;
$ref = &$a;
echo "--> State of referenced array before loop:\n";
var_dump($a);
echo "--> Do loop:\n";
foreach ($a as $k=>&$v) {
echo " iteration $counter: \$k=$k; \$v=$v\n";
eval($transform);
$counter++;
if ($counter>MAX_LOOPS) {
echo " ** Stuck in a loop! **\n";
break;
}
}
echo "--> State of array after loop:\n";
var_dump($a);
}
echo "\nPopping elements off end of a referenced array, using &\$value";
$transform = 'array_pop($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nShift elements off start of a referenced array, using &\$value";
$transform = 'array_shift($a);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nRemove current element of a referenced array, using &\$value";
$transform = 'unset($a[$k]);';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the end of a referenced array, using &\$value";
$transform = 'array_push($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
echo "\n\n\nAdding elements to the start of a referenced array, using &\$value";
$transform = 'array_unshift($a, "new.$counter");';
withRefValue(1, $transform);
withRefValue(2, $transform);
withRefValue(3, $transform);
withRefValue(4, $transform);
?>
--EXPECTF--
Popping elements off end of a referenced array, using &$value
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=0; $v=v.0
iteration 3: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
Shift elements off start of a referenced array, using &$value
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
iteration 2: $k=0; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=v.1
iteration 2: $k=0; $v=v.2
iteration 3: $k=0; $v=v.3
--> State of array after loop:
array(0) {
}
Remove current element of a referenced array, using &$value
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(0) {
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
--> State of array after loop:
array(0) {
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
--> State of array after loop:
array(0) {
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
--> State of array after loop:
array(0) {
}
Adding elements to the end of a referenced array, using &$value
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
&unicode(3) "v.0"
[1]=>
unicode(5) "new.0"
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=new.0
iteration 3: $k=3; $v=new.1
iteration 4: $k=4; $v=new.2
iteration 5: $k=5; $v=new.3
** Stuck in a loop! **
--> State of array after loop:
array(8) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(5) "new.0"
[3]=>
unicode(5) "new.1"
[4]=>
unicode(5) "new.2"
[5]=>
&unicode(5) "new.3"
[6]=>
unicode(5) "new.4"
[7]=>
unicode(5) "new.5"
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=new.0
iteration 4: $k=4; $v=new.1
iteration 5: $k=5; $v=new.2
** Stuck in a loop! **
--> State of array after loop:
array(9) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(5) "new.0"
[4]=>
unicode(5) "new.1"
[5]=>
&unicode(5) "new.2"
[6]=>
unicode(5) "new.3"
[7]=>
unicode(5) "new.4"
[8]=>
unicode(5) "new.5"
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=1; $v=v.1
iteration 2: $k=2; $v=v.2
iteration 3: $k=3; $v=v.3
iteration 4: $k=4; $v=new.0
iteration 5: $k=5; $v=new.1
** Stuck in a loop! **
--> State of array after loop:
array(10) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
[4]=>
unicode(5) "new.0"
[5]=>
&unicode(5) "new.1"
[6]=>
unicode(5) "new.2"
[7]=>
unicode(5) "new.3"
[8]=>
unicode(5) "new.4"
[9]=>
unicode(5) "new.5"
}
Adding elements to the start of a referenced array, using &$value
---( Array with 1 element(s): )---
--> State of referenced array before loop:
array(1) {
[0]=>
unicode(3) "v.0"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
--> State of array after loop:
array(2) {
[0]=>
unicode(5) "new.0"
[1]=>
&unicode(3) "v.0"
}
---( Array with 2 element(s): )---
--> State of referenced array before loop:
array(2) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(8) {
[0]=>
unicode(5) "new.5"
[1]=>
&unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
}
---( Array with 3 element(s): )---
--> State of referenced array before loop:
array(3) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(9) {
[0]=>
unicode(5) "new.5"
[1]=>
&unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
[8]=>
unicode(3) "v.2"
}
---( Array with 4 element(s): )---
--> State of referenced array before loop:
array(4) {
[0]=>
unicode(3) "v.0"
[1]=>
unicode(3) "v.1"
[2]=>
unicode(3) "v.2"
[3]=>
unicode(3) "v.3"
}
--> Do loop:
iteration 0: $k=0; $v=v.0
iteration 1: $k=0; $v=new.0
iteration 2: $k=0; $v=new.1
iteration 3: $k=0; $v=new.2
iteration 4: $k=0; $v=new.3
iteration 5: $k=0; $v=new.4
** Stuck in a loop! **
--> State of array after loop:
array(10) {
[0]=>
unicode(5) "new.5"
[1]=>
&unicode(5) "new.4"
[2]=>
unicode(5) "new.3"
[3]=>
unicode(5) "new.2"
[4]=>
unicode(5) "new.1"
[5]=>
unicode(5) "new.0"
[6]=>
unicode(3) "v.0"
[7]=>
unicode(3) "v.1"
[8]=>
unicode(3) "v.2"
[9]=>
unicode(3) "v.3"
}

View File

@ -0,0 +1,198 @@
--TEST--
Ensure foreach splits the iterated entity from its cow reference set, for all sorts of iterated entities.
--FILE--
<?php
error_reporting(E_ALL & ~E_STRICT);
echo "\n" . '$a' . "\n";
$b = $a = array('original');
foreach($a as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '${\'a\'}' . "\n";
$b = $a = array('original');
foreach(${'a'} as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$$a' . "\n";
$a = 'blah';
$$a = array('original');
$b = $$a;
foreach($$a as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a[0]' . "\n";
$b = $a[0] = array('original');
foreach($a[0] as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a[0][0]' . "\n";
$b = $a[0][0] = array('original');
foreach($a[0][0] as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a->b' . "\n";
$b = $a->b = array('original');
foreach($a->b as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a->b->c' . "\n";
$b = $a->b->c = array('original');
foreach($a->b as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a->b[0]' . "\n";
$b = $a->b[0] = array('original');
foreach($a->b[0] as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a->b[0][0]' . "\n";
$b = $a->b[0][0] = array('original');
foreach($a->b[0][0] as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . '$a->b[0]->c' . "\n";
$b = $a->b[0]->c = array('original');
foreach($a->b[0]->c as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
class C {
public static $a;
}
echo "\n" . 'C::$a' . "\n";
C::$a = array('original');
$b = C::$a;
foreach(C::$a as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset($a, $b);
echo "\n" . 'C::$a[0]' . "\n";
C::$a[0] = array('original');
$b = C::$a[0];
foreach(C::$a[0] as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset(C::$a[0], $b);
echo "\n" . 'C::$a[0]->b' . "\n";
C::$a[0]->b = array('original');
$b = C::$a[0]->b;
foreach(C::$a[0]->b as $k=>&$v) {
$v = 'changed';
}
var_dump($b);
unset(C::$a[0]->b, $b);
?>
--EXPECTF--
$a
array(1) {
[0]=>
unicode(8) "original"
}
${'a'}
array(1) {
[0]=>
unicode(8) "original"
}
$$a
array(1) {
[0]=>
unicode(8) "original"
}
$a[0]
array(1) {
[0]=>
unicode(8) "original"
}
$a[0][0]
array(1) {
[0]=>
unicode(8) "original"
}
$a->b
array(1) {
[0]=>
unicode(8) "original"
}
$a->b->c
array(1) {
[0]=>
unicode(8) "original"
}
$a->b[0]
array(1) {
[0]=>
unicode(8) "original"
}
$a->b[0][0]
array(1) {
[0]=>
unicode(8) "original"
}
$a->b[0]->c
array(1) {
[0]=>
unicode(8) "original"
}
C::$a
array(1) {
[0]=>
unicode(8) "original"
}
C::$a[0]
array(1) {
[0]=>
unicode(8) "original"
}
C::$a[0]->b
array(1) {
[0]=>
unicode(8) "original"
}

View File

@ -0,0 +1,11 @@
--TEST--
Ensure foreach works with arrays with Binary keys.
--FILE--
<?php
$a = array ( "\x90" => 10 );
foreach ($a as $val=>$key) echo $key;
echo "\nDone\n";
?>
--EXPECTF--
10
Done