php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #49723 LimitIterator with empty ArrayIterator
Submitted: 2009-09-30 13:48 UTC Modified: 2010-04-27 09:41 UTC
From: goetas at lignano dot it Assigned: colder
Status: Closed Package: SPL related
PHP Version: 5.3.0 OS: *
Private report: No CVE-ID:
 [2009-09-30 13:48 UTC] goetas at lignano dot it
Description:
------------
iterating over an empty seekable iterator causes an unexpected exception.

with actual implementation of LimitIterator::rewind() there is  no way to do  an empty loop over an empty ArrayIterator.


i suggest this implementation for  LimitIterator::rewind() method
function rewind(){
  $this->it->rewind();
  $this->pos = 0;
  if($this->it->valid()){ // check for empty iterators
      $this->seek($this->offset);
  }
}

Reproduce code:
---------------
$it = new ArrayIterator(array());

$limIt = new LimitIterator($it, 0, 5);
foreach ($limIt as $item){
	echo $item;
}

Expected result:
----------------
an empty loop

Actual result:
--------------
Uncaught exception 'OutOfBoundsException' with message 'Seek position 0 is out of range'

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-10-01 16:09 UTC] jani@php.net
Please try using this snapshot:

  http://snaps.php.net/php5.3-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/


 [2009-10-02 18:23 UTC] goetas at lignano dot it
the problem is not resolved  with php 5.3.2-dev on my apache2/winxp
 [2009-10-02 18:29 UTC] goetas at lignano dot it
source code of LimitIterator, "seek" method at line 63:

if ($this->it instanceof SeekableIterator) {
   $this->it->seek($position);  <-- there is no check if i can move pointer to $position like  on else branch
   $this->pos = $position;
} else {
  while($this->pos < $position && $this->it->valid()) {  <-- valid() ensures that i can move to $position 
    $this->next();
  }
}
 [2009-10-05 23:47 UTC] kalle@php.net
The implementation you are looking at (defined in the php files) is an outdated illustration to show how the iterator is implemented, check out:
spl_limit_it_seek() inside php-src/ext/spl/spl_iterators.c for the actual implementation.

As for whether this is a bug or not, sounds expected behaviour to me that when trying to loop over an empty range it would cause an OutOfRangeException, rather check the iterator size before trying to loop.
 [2009-10-06 15:34 UTC] goetas at lignano dot it
i think this can be a bug... or not correcty explained feature, 
becasue following code works fine:

$it = new EmptyIterator(); // EmptyIterator instead of ArrayIterator

$limIt = new LimitIterator($it, 0, 5);
foreach ($limIt as $item){
	echo $item;
}

both range are empty, but EmptyIterator does not implements SeekableIterator while ArrayIterator it does.

exception is thrown only if iterator implements SeekableIterator and is empty.
 [2010-04-27 06:57 UTC] colder@php.net
Automatic comment from SVN on behalf of colder
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=298633
Log: Fix #49723 (Skip seek when unnecessary)
 [2010-04-27 06:58 UTC] colder@php.net
Automatic comment from SVN on behalf of colder
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=298634
Log: Fix #49723 (Skip seek when unnecessary)
 [2010-04-27 09:41 UTC] colder@php.net
-Status: Assigned +Status: Closed
 [2010-04-27 09:41 UTC] colder@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Fixed by removing unnecessary seeks
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 19:01:51 2014 UTC