php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65629 SplObjectsStorage::detach() rewinds internal pointer
Submitted: 2013-09-07 03:14 UTC Modified: 2023-01-15 16:50 UTC
Votes:11
Avg. Score:4.5 ± 0.7
Reproduced:10 of 10 (100.0%)
Same Version:4 (40.0%)
Same OS:3 (30.0%)
From: alan dot bem at gmail dot com Assigned:
Status: Verified Package: SPL related
PHP Version: Irrelevant OS:
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: alan dot bem at gmail dot com
New email:
PHP Version: OS:

 

 [2013-09-07 03:14 UTC] alan dot bem at gmail dot com
Description:
------------
It seems that SplObjectsStorage::detach() internally rewinds its array pointer.

PHP versions from 5.1.0 to 5.5.3 are affected.

Test script:
---------------
// To see this live, go to: http://3v4l.org/MAELj

<?php
class A
{
    public $val;
    public function __construct($val) { $this->val = $val; }
}
$storage = new SplObjectStorage;
for($i = 1; $i <= 10; $i++) {
	$storage->attach(new A($i));
}
$iterations = 0;
$storage->rewind();
while ($storage->valid()) {
    $iterations++;
    $object = $storage->current();
    echo 'Iteration #' . $iterations . ' with object A(' . $object->val . ')';
    $storage->next();
    if($iterations === 2 || $iterations === 8) {
        $storage->detach($object);
        echo ' - deleted Object A(' . $object->val . ') ';
    }
    echo PHP_EOL;
}
echo 'Number of iterations: ' . $iterations . PHP_EOL;

Expected result:
----------------
Iteration #1 with object A(1)
Iteration #2 with object A(2) - deleted Object A(2) 
Iteration #3 with object A(3)
Iteration #4 with object A(4)
Iteration #5 with object A(5)
Iteration #6 with object A(6)
Iteration #7 with object A(7) - deleted Object A(7) 
Iteration #8 with object A(8)
Iteration #9 with object A(9)
Iteration #10 with object A(10)
Number of iterations: 10

Actual result:
--------------
Iteration #1 with object A(1)
Iteration #2 with object A(2) - deleted Object A(2) 
Iteration #3 with object A(1)
Iteration #4 with object A(3)
Iteration #5 with object A(4)
Iteration #6 with object A(5)
Iteration #7 with object A(6)
Iteration #8 with object A(7) - deleted Object A(7) 
Iteration #9 with object A(1)
Iteration #10 with object A(3)
Iteration #11 with object A(4)
Iteration #12 with object A(5)
Iteration #13 with object A(6)
Iteration #14 with object A(8)
Iteration #15 with object A(9)
Iteration #16 with object A(10)
Number of iterations: 16

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-09-12 22:49 UTC] levim@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: levim
 [2013-09-12 22:49 UTC] levim@php.net
Regardless of whether this is a bug, in general modifying a structure during 
iteration has undefined behavior. I will look a bit into this and see what might 
be done.
 [2013-09-21 23:02 UTC] levim@php.net
Bug #63917 is a duplicate of this one (has a phpt uploaded -- might be useful).
 [2015-07-20 10:08 UTC] bas at dmt-software dot nl
SplObjectsStorage::attach() does change the pointer too.
These operations should not change the internal pointer at all.
It's behaviour should be more similar to ArrayObject, it's less confusing that way.
 [2017-10-24 05:19 UTC] kalle@php.net
-Status: Verified +Status: Assigned
 [2018-08-19 16:49 UTC] cmb@php.net
> It's behaviour should be more similar to ArrayObject, it's less
> confusing that way.

Is it less confusing?  Consider:

    <?php
    $items = new ArrayObject(range(1, 10));
    foreach ($items as $key => $val) {
        unset($items[$key]);
    }
    print_r($items->getArrayCopy());

prints:

    Array
    (
        [1] => 2
        [3] => 4
        [5] => 6
        [7] => 8
        [9] => 10
    )
 [2021-10-05 15:57 UTC] artter178 at gmail dot com
Dear php team, can you fix this behaviour?
 [2023-01-15 16:50 UTC] levim@php.net
-Status: Assigned +Status: Verified -Assigned To: levim +Assigned To:
 [2023-01-15 16:50 UTC] levim@php.net
I was unable to fix this with the time I allotted. Un-assigning.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC