php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70246 ArrayIterator skips next element when current element is unset in foreach.
Submitted: 2015-08-12 12:34 UTC Modified: 2018-06-26 16:57 UTC
Votes:7
Avg. Score:3.7 ± 0.9
Reproduced:6 of 7 (85.7%)
Same Version:2 (33.3%)
Same OS:4 (66.7%)
From: arjen at react dot com Assigned:
Status: Verified Package: SPL related
PHP Version: 7.0.0beta3 OS: Linux
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: arjen at react dot com
New email:
PHP Version: OS:

 

 [2015-08-12 12:34 UTC] arjen at react dot com
Description:
------------
ArrayIterator skips next element when current element is unset in foreach.

http://3v4l.org/uUoaH

Test script:
---------------
<?php

$ar = [1,2,3,4,5];
$i = new ArrayIterator($ar);

foreach ($i as $k => $e) {
    var_dump($e);
    if ($k === 1) {
        unset($i[$k]);
    }
}

echo '---------' . PHP_EOL;

foreach ($i as $e) {
    var_dump($e);
}

Expected result:
----------------
int(1)
int(2)
int(4)
int(5)
---------
int(1)
int(3)
int(4)
int(5)

Actual result:
--------------
int(1)
int(2)
int(3)
int(4)
int(5)
---------
int(1)
int(3)
int(4)
int(5)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-08-18 11:56 UTC] arjen at react dot com
Expected and actual result are swapped, my mistake..

Expected result:
--------------
int(1)
int(2)
int(3)
int(4)
int(5)
---------
int(1)
int(3)
int(4)
int(5)

Actual result:
----------------
int(1)
int(2)
int(4)
int(5)
---------
int(1)
int(3)
int(4)
int(5)
 [2015-09-19 18:55 UTC] j dot tvr at centrum dot cz
This is probably not a bug. When you unset current element, the internal array pointer moves to the next element. Therefore what you're doing is essentially equivalent to https://3v4l.org/rWQq8:

<?php
$ar = [1, 2, 3, 4, 5];
$it = new ArrayIterator($ar);

foreach ($it as $k => $v) {
    if ($k === 0) $it->next(); // eq. to unset($it[0]);
    echo "\$ar[$k] = $v;\n";
}

echo "\n";
print_r(iterator_to_array($it));
 [2016-03-18 11:45 UTC] david at grudl dot com
Similar bug with stdClass and ArrayIterator: https://3v4l.org/2A1pf
 [2018-06-26 08:44 UTC] derick@php.net
This bug is still being encountered in the wild, and it cost us considerable time to figure out what was wrong: https://github.com/mongodb/mongo-php-library/pull/544/files#diff-d4c8c6dc8769324fc27cfdac19f05cafR88
 [2018-06-26 16:57 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2018-06-26 16:57 UTC] cmb@php.net
This regression has been introduced with commit 2b6a568[1].  The
first change in array_015.phpt already shows the problem.

[1] <http://git.php.net/?p=php-src.git;a=commit;h=2b6a568df119487f73abb43edd2ae82e83945356>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Nov 24 07:02:12 2024 UTC