From 6644e5c5ec799a41ea01f610ecd4f973aaf2db4e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 27 Apr 2005 06:46:44 +0000 Subject: [PATCH] Fixed bug #32674 (exception in iterator causes crash) --- NEWS | 1 + Zend/tests/bug32674.phpt | 62 ++++++++++++++++++++++++++++++++++++++++ Zend/zend_execute.c | 27 ++++++++++++++++- 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/bug32674.phpt diff --git a/NEWS b/NEWS index 86b5cb3b72..87da8c730b 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,7 @@ PHP NEWS (Marcus) - Fixed bug #32682 (ext/mssql: Error on module shutdown when called from activescript). (Frank) +- Fixed bug #32674 (exception in iterator causes crash). (Dmitry) - Fixed bug #32647 (Using register_shutdown_function() with invalid callback can crash PHP). (Jani) - Fixed bug #32615 (Segfault in replaceChild() using fragment when diff --git a/Zend/tests/bug32674.phpt b/Zend/tests/bug32674.phpt new file mode 100644 index 0000000000..547bcec096 --- /dev/null +++ b/Zend/tests/bug32674.phpt @@ -0,0 +1,62 @@ +--TEST-- +Bug #32674 exception in iterator causes crash +--FILE-- +_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(); + +try { + foreach($col as $co) { + //irrelevant + } + echo 'shouldn`t get here'; + //$dummy = 'this will not crash'; + $obj->dummy = 'this will crash'; +} catch (Exception $e) { + echo "ok\n"; +} +?> +--EXPECT-- +ok diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 3a26ae9d71..a1512d8c2d 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1333,7 +1333,7 @@ static int zend_check_symbol(zval **pz TSRMLS_DC) #define SET_OPCODE(new_op) \ CHECK_SYMBOL_TABLES() \ - EX(opline) = new_op; + EX(opline) = new_op; \ #define INC_OPCODE() \ if (!EG(exception)) { \ @@ -3784,6 +3784,11 @@ int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) iter->index = 0; if (iter->funcs->rewind) { iter->funcs->rewind(iter TSRMLS_CC); + if (EG(exception)) { + array_ptr->refcount--; + zval_ptr_dtor(&array_ptr); + NEXT_OPCODE(); + } } } else if ((fe_ht = HASH_OF(array_ptr)) != NULL) { /* probably redundant */ @@ -3860,13 +3865,28 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) /* This could cause an endless loop if index becomes zero again. * In case that ever happens we need an additional flag. */ iter->funcs->move_forward(iter TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } } if (!iter || iter->funcs->valid(iter TSRMLS_CC) == FAILURE) { /* reached end of iteration */ + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); return 0; /* CHECK_ME */ } iter->funcs->get_current_data(iter, &value TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } if (!value) { /* failure in get_current_data */ SET_OPCODE(op_array->opcodes+opline->op2.u.opline_num); @@ -3874,6 +3894,11 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) } if (iter->funcs->get_current_key) { key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { + array->refcount--; + zval_ptr_dtor(&array); + NEXT_OPCODE(); + } } else { key_type = HASH_KEY_IS_LONG; int_key = iter->index; -- 2.50.1