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
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: 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: Sun Nov 24 04:01:32 2024 UTC