Skip to content

Commit da0663a

Browse files
committed
Add GC_TRY_ADDREF macro
That adds a ref if not immutable. Also audit uses of GC_IMMUTABLE to either use GC_TRY_ADDREF or GC_TRY_PROTECT_RECURSION.
1 parent 1bffe6b commit da0663a

File tree

7 files changed

+27
-34
lines changed

7 files changed

+27
-34
lines changed

Zend/zend.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,7 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */
404404
}
405405
print_flat_hash(Z_ARRVAL_P(expr));
406406
ZEND_PUTS(")");
407-
if (!(GC_FLAGS(Z_ARRVAL_P(expr)) & GC_IMMUTABLE)) {
408-
GC_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
409-
}
407+
GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
410408
break;
411409
case IS_OBJECT:
412410
{
@@ -452,9 +450,7 @@ static void zend_print_zval_r_to_buf(smart_str *buf, zval *expr, int indent) /*
452450
GC_PROTECT_RECURSION(Z_ARRVAL_P(expr));
453451
}
454452
print_hash(buf, Z_ARRVAL_P(expr), indent, 0);
455-
if (!(GC_FLAGS(Z_ARRVAL_P(expr)) & GC_IMMUTABLE)) {
456-
GC_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
457-
}
453+
GC_TRY_UNPROTECT_RECURSION(Z_ARRVAL_P(expr));
458454
break;
459455
case IS_OBJECT:
460456
{

Zend/zend_hash.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,13 +2658,9 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
26582658
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
26592659
}
26602660

2661-
if (!(GC_FLAGS(ht1) & GC_IMMUTABLE)) {
2662-
GC_PROTECT_RECURSION(ht1);
2663-
}
2661+
GC_TRY_PROTECT_RECURSION(ht1);
26642662
result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
2665-
if (!(GC_FLAGS(ht1) & GC_IMMUTABLE)) {
2666-
GC_UNPROTECT_RECURSION(ht1);
2667-
}
2663+
GC_TRY_UNPROTECT_RECURSION(ht1);
26682664

26692665
return result;
26702666
}

Zend/zend_object_handlers.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,8 +1776,8 @@ ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purp
17761776
if (obj->handlers->get_debug_info) {
17771777
int is_temp;
17781778
ht = obj->handlers->get_debug_info(obj, &is_temp);
1779-
if (ht && !is_temp && !(GC_FLAGS(ht) & GC_IMMUTABLE)) {
1780-
GC_ADDREF(ht);
1779+
if (ht && !is_temp) {
1780+
GC_TRY_ADDREF(ht);
17811781
}
17821782
return ht;
17831783
}
@@ -1787,8 +1787,8 @@ ZEND_API HashTable *zend_std_get_properties_for(zend_object *obj, zend_prop_purp
17871787
case ZEND_PROP_PURPOSE_VAR_EXPORT:
17881788
case ZEND_PROP_PURPOSE_JSON:
17891789
ht = obj->handlers->get_properties(obj);
1790-
if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) {
1791-
GC_ADDREF(ht);
1790+
if (ht) {
1791+
GC_TRY_ADDREF(ht);
17921792
}
17931793
return ht;
17941794
default:

Zend/zend_types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
612612
#define GC_DELREF(p) zend_gc_delref(&(p)->gc)
613613
#define GC_ADDREF_EX(p, rc) zend_gc_addref_ex(&(p)->gc, rc)
614614
#define GC_DELREF_EX(p, rc) zend_gc_delref_ex(&(p)->gc, rc)
615+
#define GC_TRY_ADDREF(p) zend_gc_try_addref(&(p)->gc)
615616

616617
#define GC_TYPE_MASK 0x0000000f
617618
#define GC_FLAGS_MASK 0x000003f0
@@ -1160,6 +1161,13 @@ static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
11601161
return ++(p->refcount);
11611162
}
11621163

1164+
static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) {
1165+
if (!(p->u.type_info & GC_IMMUTABLE)) {
1166+
ZEND_RC_MOD_CHECK(p);
1167+
++p->refcount;
1168+
}
1169+
}
1170+
11631171
static zend_always_inline uint32_t zend_gc_delref(zend_refcounted_h *p) {
11641172
ZEND_ASSERT(p->refcount > 0);
11651173
ZEND_RC_MOD_CHECK(p);

ext/json/json_encoder.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,15 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options)
113113

114114
#define PHP_JSON_HASH_PROTECT_RECURSION(_tmp_ht) \
115115
do { \
116-
if (_tmp_ht && !(GC_FLAGS(_tmp_ht) & GC_IMMUTABLE)) { \
117-
GC_PROTECT_RECURSION(_tmp_ht); \
116+
if (_tmp_ht) { \
117+
GC_TRY_PROTECT_RECURSION(_tmp_ht); \
118118
} \
119119
} while (0)
120120

121121
#define PHP_JSON_HASH_UNPROTECT_RECURSION(_tmp_ht) \
122122
do { \
123-
if (_tmp_ht && !(GC_FLAGS(_tmp_ht) & GC_IMMUTABLE)) { \
124-
GC_UNPROTECT_RECURSION(_tmp_ht); \
123+
if (_tmp_ht) { \
124+
GC_TRY_UNPROTECT_RECURSION(_tmp_ht); \
125125
} \
126126
} while (0)
127127

ext/standard/array.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -716,10 +716,7 @@ PHPAPI zend_long php_count_recursive(HashTable *ht) /* {{{ */
716716
}
717717
} ZEND_HASH_FOREACH_END();
718718

719-
if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
720-
GC_UNPROTECT_RECURSION(ht);
721-
}
722-
719+
GC_TRY_UNPROTECT_RECURSION(ht);
723720
return cnt;
724721
}
725722
/* }}} */
@@ -3644,12 +3641,12 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
36443641
src_zval = &tmp;
36453642
}
36463643
if (Z_TYPE_P(src_zval) == IS_ARRAY) {
3647-
if (thash && !(GC_FLAGS(thash) & GC_IMMUTABLE)) {
3648-
GC_PROTECT_RECURSION(thash);
3644+
if (thash) {
3645+
GC_TRY_PROTECT_RECURSION(thash);
36493646
}
36503647
ret = php_array_merge_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
3651-
if (thash && !(GC_FLAGS(thash) & GC_IMMUTABLE)) {
3652-
GC_UNPROTECT_RECURSION(thash);
3648+
if (thash) {
3649+
GC_TRY_UNPROTECT_RECURSION(thash);
36533650
}
36543651
if (!ret) {
36553652
return 0;

ext/standard/http.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,9 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
146146
*(p++) = 'B';
147147
*p = '\0';
148148
}
149-
if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
150-
GC_PROTECT_RECURSION(ht);
151-
}
149+
GC_TRY_PROTECT_RECURSION(ht);
152150
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);
153-
if (!(GC_FLAGS(ht) & GC_IMMUTABLE)) {
154-
GC_UNPROTECT_RECURSION(ht);
155-
}
151+
GC_TRY_UNPROTECT_RECURSION(ht);
156152
efree(newprefix);
157153
} else if (Z_TYPE_P(zdata) == IS_NULL || Z_TYPE_P(zdata) == IS_RESOURCE) {
158154
/* Skip these types */

0 commit comments

Comments
 (0)