]> granicus.if.org Git - php/commitdiff
Make zend_hash_apply_deleter() void, to allow reuse
authorNikita Popov <nikic@php.net>
Thu, 20 Mar 2014 22:25:53 +0000 (23:25 +0100)
committerNikita Popov <nikic@php.net>
Thu, 20 Mar 2014 23:14:51 +0000 (00:14 +0100)
Also remove lies in the comment above the function. apply_deleter
is not safe against modification, if the modification involves
removing the next bucket.

Also modified the implementation of zend_hash_graceful_destroy()
to be fully graceful (the reverse variant already was).

Zend/zend_hash.c

index ac713c6addb7fa149bc52de621848be22003ea5a..ab8601c2ebe22b4f663d2fab52f7321a85d4d4fd 100644 (file)
@@ -543,13 +543,10 @@ ZEND_API void zend_hash_clean(HashTable *ht)
 }
 
 /* This function is used by the various apply() functions.
- * It deletes the passed bucket, and returns the address of the
- * next bucket.  The hash *may* be altered during that time, the
- * returned value will still be valid.
+ * It deletes the passed bucket.
  */
-static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
+static void zend_hash_apply_deleter(HashTable *ht, Bucket *p)
 {
-       Bucket *retval;
 #ifdef ZEND_SIGNALS
        TSRMLS_FETCH();
 #endif
@@ -592,23 +589,18 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
        if (p->pData != &p->pDataPtr) {
                pefree(p->pData, ht->persistent);
        }
-       retval = p->pListNext;
        pefree(p, ht->persistent);
-
-       return retval;
 }
 
 
 ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
 {
-       Bucket *p;
-
        IS_CONSISTENT(ht);
 
-       p = ht->pListHead;
-       while (p != NULL) {
-               p = zend_hash_apply_deleter(ht, p);
+       while (ht->pListHead != NULL) {
+               zend_hash_apply_deleter(ht, ht->pListHead);
        }
+
        if (ht->nTableMask) {
                pefree(ht->arBuckets, ht->persistent);
        }
@@ -618,14 +610,10 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
 
 ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
 {
-       Bucket *p;
-
        IS_CONSISTENT(ht);
 
-       p = ht->pListTail;
-       while (p != NULL) {
-               zend_hash_apply_deleter(ht, p);
-               p = ht->pListTail;
+       while (ht->pListTail != NULL) {
+               zend_hash_apply_deleter(ht, ht->pListTail);
        }
 
        if (ht->nTableMask) {
@@ -654,12 +642,13 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
        p = ht->pListHead;
        while (p != NULL) {
                int result = apply_func(p->pData TSRMLS_CC);
-               
+
+               Bucket *p_next = p->pListNext;
                if (result & ZEND_HASH_APPLY_REMOVE) {
-                       p = zend_hash_apply_deleter(ht, p);
-               } else {
-                       p = p->pListNext;
+                       zend_hash_apply_deleter(ht, p);
                }
+               p = p_next;
+
                if (result & ZEND_HASH_APPLY_STOP) {
                        break;
                }
@@ -679,11 +668,12 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t appl
        while (p != NULL) {
                int result = apply_func(p->pData, argument TSRMLS_CC);
                
+               Bucket *p_next = p->pListNext;
                if (result & ZEND_HASH_APPLY_REMOVE) {
-                       p = zend_hash_apply_deleter(ht, p);
-               } else {
-                       p = p->pListNext;
+                       zend_hash_apply_deleter(ht, p);
                }
+               p = p_next;
+
                if (result & ZEND_HASH_APPLY_STOP) {
                        break;
                }
@@ -711,11 +701,12 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
                hash_key.h = p->h;
                result = apply_func(p->pData TSRMLS_CC, num_args, args, &hash_key);
 
+               Bucket *p_next = p->pListNext;
                if (result & ZEND_HASH_APPLY_REMOVE) {
-                       p = zend_hash_apply_deleter(ht, p);
-               } else {
-                       p = p->pListNext;
+                       zend_hash_apply_deleter(ht, p);
                }
+               p = p_next;
+
                if (result & ZEND_HASH_APPLY_STOP) {
                        va_end(args);
                        break;
@@ -729,7 +720,7 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
 
 ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
 {
-       Bucket *p, *q;
+       Bucket *p;
 
        IS_CONSISTENT(ht);
 
@@ -738,11 +729,12 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
        while (p != NULL) {
                int result = apply_func(p->pData TSRMLS_CC);
 
-               q = p;
-               p = p->pListLast;
+               Bucket *p_last = p->pListLast;
                if (result & ZEND_HASH_APPLY_REMOVE) {
-                       zend_hash_apply_deleter(ht, q);
+                       zend_hash_apply_deleter(ht, p);
                }
+               p = p_last;
+
                if (result & ZEND_HASH_APPLY_STOP) {
                        break;
                }