summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Boerger <helly@php.net>2005-03-21 20:07:33 +0000
committerMarcus Boerger <helly@php.net>2005-03-21 20:07:33 +0000
commit041524feeef3bce21ce8a15d538cb766b04f8b7f (patch)
tree469116b280553a138a71d7b3f91a745151beb28a
parent756c5784c156148c9dd4b32c4495e765af8b7bd4 (diff)
downloadphp-git-041524feeef3bce21ce8a15d538cb766b04f8b7f.tar.gz
- Fix Bug #32394 offsetUnset() segfaults in a foreach
-rwxr-xr-xext/spl/spl_array.c75
-rwxr-xr-xext/spl/tests/bug32394.phpt17
2 files changed, 55 insertions, 37 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 621b8a73a2..bbecc5ffa1 100755
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -134,6 +134,27 @@ typedef struct _spl_array_object {
zend_function * fptr_offset_del;
} spl_array_object;
+SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
+{
+ HashTable *ht = HASH_OF(intern->array);
+ Bucket *p;
+
+/* IS_CONSISTENT(ht);*/
+
+/* HASH_PROTECT_RECURSION(ht);*/
+ p = ht->pListHead;
+ while (p != NULL) {
+ if (p == intern->pos) {
+ return SUCCESS;
+ }
+ p = p->pListNext;
+ }
+/* HASH_UNPROTECT_RECURSION(ht); */
+ zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
+ return FAILURE;
+}
+/* }}} */
+
/* {{{ spl_array_object_free_storage */
static void spl_array_object_free_storage(void *object TSRMLS_DC)
{
@@ -352,7 +373,7 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
}
}
- return;
+ break;
case IS_DOUBLE:
case IS_RESOURCE:
case IS_BOOL:
@@ -365,11 +386,12 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
if (zend_hash_index_del(HASH_OF(intern->array), index) == FAILURE) {
zend_error(E_NOTICE,"Undefined offset: %ld", Z_LVAL_P(offset));
}
- return;
+ break;
default:
zend_error(E_WARNING, "Illegal offset type");
return;
}
+ spl_hash_verify_pos(intern TSRMLS_CC); /* call rewind on FAILURE */
} /* }}} */
static void spl_array_unset_dimension(zval *object, zval *offset TSRMLS_DC) /* {{{ */
@@ -521,27 +543,6 @@ static HashTable *spl_array_get_properties(zval *object TSRMLS_DC)
}
/* }}} */
-SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
-{
- HashTable *ht = HASH_OF(intern->array);
- Bucket *p;
-
-/* IS_CONSISTENT(ht);*/
-
-/* HASH_PROTECT_RECURSION(ht);*/
- p = ht->pListHead;
- while (p != NULL) {
- if (p == intern->pos) {
- return SUCCESS;
- }
- p = p->pListNext;
- }
-/* HASH_UNPROTECT_RECURSION(ht); */
- zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
- return FAILURE;
-}
-/* }}} */
-
static int spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ */
{
char *string_key;
@@ -673,19 +674,26 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
}
/* }}} */
-static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
+static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */
{
- spl_array_it *iterator = (spl_array_it *)iter;
- spl_array_object *object = iterator->object;
- HashTable *aht = HASH_OF(object->array);
+ HashTable *aht = HASH_OF(intern->array);
if (!aht) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array");
return;
}
- zend_hash_internal_pointer_reset_ex(aht, &object->pos);
- spl_array_skip_protected(object TSRMLS_CC);
+ zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
+ spl_array_skip_protected(intern TSRMLS_CC);
+}
+/* }}} */
+
+static void spl_array_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
+{
+ spl_array_it *iterator = (spl_array_it *)iter;
+ spl_array_object *object = iterator->object;
+
+ spl_array_rewind(object TSRMLS_CC);
}
/* }}} */
@@ -782,15 +790,8 @@ SPL_METHOD(Array, rewind)
{
zval *object = getThis();
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
- HashTable *aht = HASH_OF(intern->array);
-
- if (!aht) {
- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
- return;
- }
- zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
- spl_array_skip_protected(intern TSRMLS_CC);
+ spl_array_rewind(intern TSRMLS_CC);
}
/* }}} */
diff --git a/ext/spl/tests/bug32394.phpt b/ext/spl/tests/bug32394.phpt
new file mode 100755
index 0000000000..8189b23f7a
--- /dev/null
+++ b/ext/spl/tests/bug32394.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #32394 (offsetUnset() segfaults in a foreach)
+--FILE--
+<?php
+
+$object = new ArrayIterator;
+$object->append(1);
+
+foreach($object as $key => $value)
+{
+ $object->offsetUnset($key);
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===