php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79726 SplStack::pop breaks stack validity
Submitted: 2020-06-23 14:25 UTC Modified: 2020-07-13 09:12 UTC
From: millet dot gael at gmail dot com Assigned:
Status: Wont fix Package: SPL related
PHP Version: 7.4.7 OS: OSX
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 this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: millet dot gael at gmail dot com
New email:
PHP Version: OS:

 

 [2020-06-23 14:25 UTC] millet dot gael at gmail dot com
Description:
------------
Breaking change on SplStack iterator.
If we pop from the stack, the stack become invalid for the last iteration.
This code was working with php 7.2.x, but is broken with 7.3.x and 7.4.x

Can be fixed by adding "$stack->rewind();" after "$stack->next();"

Test script:
---------------
<?php
$stack = new \SplStack();
$stack->push(1);
$stack->push(2);
$stack->rewind();
while ($stack->valid()) {
    $value = $stack->pop();
    var_dump($value);
    $stack->next();
}

Expected result:
----------------
int(2)
int(1)

Actual result:
--------------
int(2)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-06-23 14:45 UTC] Wes dot example at example dot org
The fact that worked before was probably accidental. Changing any data structure while iterating over it, will produce this sort of errors. That's not just SPL or PHP, but happens in any programming language, and it's disallowed by design in most of the times.

Your specific bug can be fixed, probably, but you should avoid that sort of code anyway. If you get any kind of reasonable result from doing this, always consider it a hack, or accidental. Unless you are actually iterating over a copy (like PHP arrays) or using something like ->filter() array_filter() functions.
 [2020-06-24 07:03 UTC] millet dot gael at gmail dot com
I fixed my code, but I think it's still a bug.
Here is the weirdest part : https://3v4l.org/GPvYk

The previous code is working with 7.2.0 - 7.3.14, 7.4.0 - 7.4.2 and fails with 7.3.15 - 7.3.19, 7.4.3 - 7.4.7

The behaviour is unpredictable depending of the php version.
 [2020-06-24 07:55 UTC] cmb@php.net
The behavior likely changed due to fixing bug #79151.  In my
opinion, this change is not a bug, but rather the given test code
is invalid; valid alternatives would be <https://3v4l.org/fZKT8>
and <https://3v4l.org/HLrZn>.
 [2020-06-24 08:08 UTC] nikic@php.net
I guess we could check whether traverse_pointer is equal to the popped element and reset the pointer in that case.

I'm inclined to agree that this is "Won't Fix" though. The provided code doesn't make sense.
 [2020-07-13 09:12 UTC] nikic@php.net
-Status: Open +Status: Wont fix
 [2020-07-13 09:12 UTC] nikic@php.net
Marking this won't fix per comments above.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 07:01:31 2024 UTC