php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70471 foreach skips values with array_splice
Submitted: 2015-09-10 19:21 UTC Modified: 2021-11-16 13:27 UTC
Votes:6
Avg. Score:4.3 ± 0.9
Reproduced:4 of 5 (80.0%)
Same Version:3 (75.0%)
Same OS:2 (50.0%)
From: dev at cmr dot cx Assigned:
Status: Open Package: Arrays related
PHP Version: 7.0.0RC2 OS: Linux
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: dev at cmr dot cx
New email:
PHP Version: OS:

 

 [2015-09-10 19:21 UTC] dev at cmr dot cx
Description:
------------
In the expample skript foreach skips the values "c", "d" and "e".

As far as I can see this happens only if in the array_splice the number of elements of the replacement array (array("x", "y")) is higher than the length parameter (1). If I set the length to 2, I get the following output, which makes much more sense:

0: a
1: b
3: d
4: e
5: f
Array
(
    [0] => a
    [1] => x
    [2] => y
    [3] => d
    [4] => e
    [5] => f
)  

Test script:
---------------
$array = array("a", "b", "c", "d", "e", "f");
foreach ( $array as $key => &$value ) {
	echo "$key: $value\n";
	if ( $value == "b" ) array_splice($array, $key, 1, array("x", "y"));
}
print_r($array);

Expected result:
----------------
0: a
1: b
3: c
4: d
5: e
6: f
Array
(
    [0] => a
    [1] => x
    [2] => y
    [3] => c
    [4] => d
    [5] => e
    [6] => f
)

Actual result:
--------------
0: a
1: b
6: f
Array
(
    [0] => a
    [1] => x
    [2] => y
    [3] => c
    [4] => d
    [5] => e
    [6] => f
)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-09-19 19:37 UTC] j dot tvr at centrum dot cz
The issue is still valid with PHP 7.0.0RC3. However I personally think that the expected result should not skip the key 2 with y value, i.e. it should be

0: a
1: b
2: y
3: c
4: d
5: e
6: f
Array
(
    [0] => a
    [1] => x
    [2] => y
    [3] => c
    [4] => d
    [5] => e
    [6] => f
)


This following is a bit simplified test script:

<?php
$ar = ['a', 'b', 'c'];

foreach ($ar as $k => &$v) {
	echo "$k: $v\n";
	if ($k === 0) array_splice($ar, 1, 0, ['x']);
}

echo "\n";
print_r($ar);


Expected result:
----------------
0: a
1: x
2: b
3: c

Array
(
    [0] => a
    [1] => x
    [2] => b
    [3] => c
)
 [2015-09-20 01:02 UTC] nikic@php.net
The problem is that the iterator bump in http://lxr.php.net/xref/PHP_TRUNK/ext/standard/array.c#2469 can (unlike most other cases) move an iterator forward, which the code doesn't account for. (The iterator will just be bumped forward again and again in that loop.)
 [2021-11-16 13:27 UTC] cmb@php.net
For reference: <https://3v4l.org/rEQN8>.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 17:01:58 2024 UTC