php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #32674 exception in iterator causes crash
Submitted: 2005-04-11 17:26 UTC Modified: 2005-04-27 08:48 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: rashid at ds dot pg dot gda dot pl Assigned: andi
Status: Closed Package: Scripting Engine problem
PHP Version: 5CVS-2005-04-11 OS: *
Private report: No CVE-ID:
 [2005-04-11 17:26 UTC] rashid at ds dot pg dot gda dot pl
Description:
------------
If you create class implementing Iterator interface and exception happens during foreach than hell breaks loose. After exception in foreach debugger shows, that processing is continued in line after the loop. In this situation exception should be thrown further. Instead it looks like exception is being kept somewhere while processing continues and is being thrown at end of the script (end of scope?).

Normally (ie. operations on non-objects) this doesn`t cause crash, but if you assign object member after interrupted loop, then apache dies (1.3.28).

Apart from latest shapshot the problem is present also in 5.0.3, didn`t check 5.0.4.

Reproduce code:
---------------
<?php
class collection implements Iterator {

  private $_elements = array();

  public function __construct() {
  }


  public function rewind() {
    reset($this->_elements);
  }

  public function count() {
    return count($this->_elements);
  }

  public function current() {
    $element = current($this->_elements);
    return $element;
  }

  public function next() {
    $element = next($this->_elements);
    return $element;
  }

  public function key() {
    $this->_fillCollection();
    $element = key($this->_elements);
    return $element;
  }

  public function valid() {
    throw new Exception('shit happend');

    return ($this->current() !== false);
  }
}

class class2 {
  public $dummy;
}

$obj = new class2();
$col = new collection();
$dummy = 'nothing';

foreach($col as $co) {
  //irrelevant
}

echo 'shouldn`t get here';
//$dummy = 'this will not crash'; 
$obj->dummy = 'this will crash';
?>

Expected result:
----------------
Fatal error: Uncaught exception 'Exception' with message 'shit happend' in d:\projects\opcapp\htdocs\collcrash.php:35 Stack trace: #0 d:\projects\opcapp\htdocs\collcrash.php(35): collection::valid() #1 d:\projects\opcapp\htdocs\collcrash.php(49): collection::valid() #2 d:\projects\opcapp\htdocs\collcrash.php(49): unknown() #3 {main} thrown in d:\projects\opcapp\htdocs\collcrash.php on line 35

Actual result:
--------------
apache crash 

or (if you comment out the bottom line and remove comment from the one above it)

shouldn`t get here
Fatal error: Uncaught exception 'Exception' with message 'shit happend' in d:\projects\opcapp\htdocs\collcrash.php:35 Stack trace: #0 d:\projects\opcapp\htdocs\collcrash.php(35): collection::valid() #1 d:\projects\opcapp\htdocs\collcrash.php(49): collection::valid() #2 d:\projects\opcapp\htdocs\collcrash.php(49): unknown() #3 {main} thrown in d:\projects\opcapp\htdocs\collcrash.php on line 35

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-04-11 17:50 UTC] sniper@php.net
I get this:

Fatal error: Invalid opcode 137/1/8. in /home/jani/t.php on line 50

 [2005-04-12 10:30 UTC] helly@php.net
The illegal opcde error can be produced easily. Actually no iterator method that throws an exception doesn't result in direct script termination in case of try/catch block absence. This said a much easier test case is the following:
--TEST--
Bug #32674 (exception in iterator causes crash).
--FILE--
<?php
class MyCollection implements Iterator
{
	public function rewind() { }
	
	public function current() { }
	
	public function next() { }
	
	public function key() {	}
	
	public function valid()
	{
		throw new Exception('shit happend');
	}
}
	
$obj = new stdClass();
$col = new MyCollection();
	
foreach($col as $co)
{
	//irrelevant
}

echo 'shouldn`t get here';
$obj->dummy = 'this will crash';
exit(0);
?>
===DONE===
--EXPECTF--

Unfortunatley even handling exceptions for all method calls in FE_RESET and FE_FETCH opcode doesn't help since then SWITCH_FREE still ignores the exception.

In the end it seems that this is an error where either the executor loop needs to check for the exceptions or the lw level function handler needs to do a direct long jump on exceptions (the latter is bad because it doesn't free anything and ha problems with catch blocks).
 [2005-04-27 08:47 UTC] dmitry@php.net
Fixed in CVS HEAD and PHP_5_0.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 16 22:02:05 2014 UTC