summaryrefslogtreecommitdiff
path: root/Zend/zend_operators.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2021-02-16 09:55:02 +0100
committerNikita Popov <nikita.ppv@gmail.com>2021-02-16 10:01:46 +0100
commit353f7ffb6b3f6e7c3aed8b3ed51182a973e120b8 (patch)
tree94f18859fc5eb42be1ac4bea3545b6bf00a91377 /Zend/zend_operators.c
parent0cdc634fc4f233034c37234d98f5ff3d6cf216b2 (diff)
downloadphp-git-353f7ffb6b3f6e7c3aed8b3ed51182a973e120b8.tar.gz
Delref only after successful allocation
Otherwise we may have inconsistent refcounts after OOM. I expect this problem is much more prevalent, but this at least fixes some string/array separation cases. Fixes oss-fuzz #30999.
Diffstat (limited to 'Zend/zend_operators.c')
-rw-r--r--Zend/zend_operators.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 29b2ed79b8..0cdb3aa085 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -2323,8 +2323,10 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
Z_TYPE_INFO_P(str) = IS_STRING_EX;
} else if (Z_REFCOUNT_P(str) > 1) {
- Z_DELREF_P(str);
+ /* Only release string after allocation succeeded. */
+ zend_string *orig_str = Z_STR_P(str);
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
+ GC_DELREF(orig_str);
} else {
zend_string_forget_hash_val(Z_STR_P(str));
}