]> granicus.if.org Git - php/commitdiff
Add GC_TRY_ADDREF macro
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 15 Sep 2020 09:38:40 +0000 (11:38 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 15 Sep 2020 09:41:09 +0000 (11:41 +0200)
That adds a ref if not immutable. Also audit uses of GC_IMMUTABLE
to either use GC_TRY_ADDREF or GC_TRY_PROTECT_RECURSION.

Zend/zend.c
Zend/zend_hash.c
Zend/zend_object_handlers.c
Zend/zend_types.h
ext/json/json_encoder.c
ext/standard/array.c
ext/standard/http.c

index 4d781e6a10738eb07e751a9c704aebeb3b4d6cd2..cbd5aef42b9fece82611b0a330987c53bffcd1cc 100644 (file)
@@ -404,9 +404,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */
                        }
                        print_flat_hash(Z_ARRVAL_P(expr));
                        ZEND_PUTS(")");
-                       if (!(GC_FLAGS(Z_ARRVAL_P(expr)) & GC_IMMUTABLE)) {
-                               GC_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
-                       }
+                       GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
                        break;
                case IS_OBJECT:
                {
@@ -452,9 +450,7 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
                                GC_PROTECT_RECURSION(Z_ARRVAL_P(expr));
                        }
                        print_hash(buf, Z_ARRVAL_P(expr), indent, 0);
-                       if (!(GC_FLAGS(Z_ARRVAL_P(expr)) & GC_IMMUTABLE)) {
-                               GC_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
-                       }
+                       GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
                        break;
                case IS_OBJECT:
                        {
index abda03edf631e66284d8e41da6f3515a96e4ec1a..c92b869569fcb78d03b75066fd31ea57be92e685 100644 (file)
@@ -2658,13 +2658,9 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
                zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
        }
 
-       if (!(GC_FLAGS(ht1) & GC_IMMUTABLE)) {
-               GC_PROTECT_RECURSION(ht1);
-       }
+       GC_TRY_PROTECT_RECURSION(ht1);
        result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
-       if (!(GC_FLAGS(ht1) & GC_IMMUTABLE)) {
-               GC_UNPROTECT_RECURSION(ht1);
-       }
+       GC_TRY_UNPROTECT_RECURSION(ht1);
 
        return result;
 }
index a4ee0feda8a83e37b31ea87299677329f3729236..be8ab3aca7c978cf74c03d26abae3f701d4915cf 100644 (file)
@@ -1776,8 +1776,8 @@ ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purp
                        if (obj->handlers->get_debug_info) {
                                int is_temp;
                                ht = obj->handlers->get_debug_info(obj, &is_temp);
-                               if (ht && !is_temp && !(GC_FLAGS(ht) & GC_IMMUTABLE)) {
-                                       GC_ADDREF(ht);
+                               if (ht && !is_temp) {
+                                       GC_TRY_ADDREF(ht);
                                }
                                return ht;
                        }
@@ -1787,8 +1787,8 @@ ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purp
                case ZEND_PROP_PURPOSE_VAR_EXPORT:
                case ZEND_PROP_PURPOSE_JSON:
                        ht = obj->handlers->get_properties(obj);
-                       if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) {
-                               GC_ADDREF(ht);
+                       if (ht) {
+                               GC_TRY_ADDREF(ht);
                        }
                        return ht;
                default:
index 745be6e93830c43199745480fb129d5c1a0c6d14..3b1ec85452ff3d55911f0e05931634e4e8bd8010 100644 (file)
@@ -612,6 +612,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
 #define GC_DELREF(p)                           zend_gc_delref(&(p)->gc)
 #define GC_ADDREF_EX(p, rc)                    zend_gc_addref_ex(&(p)->gc, rc)
 #define GC_DELREF_EX(p, rc)                    zend_gc_delref_ex(&(p)->gc, rc)
+#define GC_TRY_ADDREF(p)                       zend_gc_try_addref(&(p)->gc)
 
 #define GC_TYPE_MASK                           0x0000000f
 #define GC_FLAGS_MASK                          0x000003f0
@@ -1160,6 +1161,13 @@ static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
        return ++(p->refcount);
 }
 
+static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) {
+       if (!(p->u.type_info & GC_IMMUTABLE)) {
+               ZEND_RC_MOD_CHECK(p);
+               ++p->refcount;
+       }
+}
+
 static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
        ZEND_ASSERT(p->refcount > 0);
        ZEND_RC_MOD_CHECK(p);
index d08a4666435d1d32990371b2a508d3c39ce42d96..92e4a109339575350e693d0260d17d48ed7a4b94 100644 (file)
@@ -113,15 +113,15 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options)
 
 #define PHP_JSON_HASH_PROTECT_RECURSION(_tmp_ht) \
        do { \
-               if (_tmp_ht && !(GC_FLAGS(_tmp_ht) & GC_IMMUTABLE)) { \
-                       GC_PROTECT_RECURSION(_tmp_ht); \
+               if (_tmp_ht) { \
+                       GC_TRY_PROTECT_RECURSION(_tmp_ht); \
                } \
        } while (0)
 
 #define PHP_JSON_HASH_UNPROTECT_RECURSION(_tmp_ht) \
        do { \
-               if (_tmp_ht && !(GC_FLAGS(_tmp_ht) & GC_IMMUTABLE)) { \
-                       GC_UNPROTECT_RECURSION(_tmp_ht); \
+               if (_tmp_ht) { \
+                       GC_TRY_UNPROTECT_RECURSION(_tmp_ht); \
                } \
        } while (0)
 
index cb5e6e7dee6f1159ac475da58dff44fe406073e2..58c4d815b7c80163ef72c016e7cf12063e1c8d15 100644 (file)
@@ -716,10 +716,7 @@ PHPAPI zend_long php_count_recursive(HashTable *ht) /* {{{ */
                }
        } ZEND_HASH_FOREACH_END();
 
-       if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
-               GC_UNPROTECT_RECURSION(ht);
-       }
-
+       GC_TRY_UNPROTECT_RECURSION(ht);
        return cnt;
 }
 /* }}} */
@@ -3644,12 +3641,12 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
                                        src_zval = &tmp;
                                }
                                if (Z_TYPE_P(src_zval) == IS_ARRAY) {
-                                       if (thash && !(GC_FLAGS(thash) & GC_IMMUTABLE)) {
-                                               GC_PROTECT_RECURSION(thash);
+                                       if (thash) {
+                                               GC_TRY_PROTECT_RECURSION(thash);
                                        }
                                        ret = php_array_merge_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
-                                       if (thash && !(GC_FLAGS(thash) & GC_IMMUTABLE)) {
-                                               GC_UNPROTECT_RECURSION(thash);
+                                       if (thash) {
+                                               GC_TRY_UNPROTECT_RECURSION(thash);
                                        }
                                        if (!ret) {
                                                return 0;
index 3819065894a71e375d0f58e6fb3238193aaf741b..804940fd1a63e17abff61f550356b5f4ac121e3c 100644 (file)
@@ -146,13 +146,9 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
                                *(p++) = 'B';
                                *p = '\0';
                        }
-                       if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
-                               GC_PROTECT_RECURSION(ht);
-                       }
+                       GC_TRY_PROTECT_RECURSION(ht);
                        php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, newprefix, newprefix_len, "%5D", 3, (Z_TYPE_P(zdata) == IS_OBJECT ? zdata : NULL), arg_sep, enc_type);
-                       if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
-                               GC_UNPROTECT_RECURSION(ht);
-                       }
+                       GC_TRY_UNPROTECT_RECURSION(ht);
                        efree(newprefix);
                } else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) {
                        /* Skip these types */