summaryrefslogtreecommitdiff
path: root/Zend/zend_execute.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-07-07 12:17:11 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-07-07 12:28:35 +0200
commit2c73bf7e3fc470e8e50cc7283844c9b1d7c2a9d2 (patch)
tree8e1f2746f4ee9fd761804f3a8bd73085eb0774f3 /Zend/zend_execute.c
parentecf368b8f2b9d578f3f9bb23f48d5920adbdccbb (diff)
parent220880ad2d54d10173a250637478da213b1ae8e2 (diff)
downloadphp-git-2c73bf7e3fc470e8e50cc7283844c9b1d7c2a9d2.tar.gz
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug #78598
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r--Zend/zend_execute.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index fcd2a437e6..f49b005a14 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1909,6 +1909,44 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_index(const
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset));
}
+static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_offset_write(
+ HashTable *ht, zend_long lval)
+{
+ /* The array may be destroyed while throwing the notice.
+ * Temporarily increase the refcount to detect this situation. */
+ if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
+ GC_ADDREF(ht);
+ }
+ zend_undefined_offset(lval);
+ if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
+ zend_array_destroy(ht);
+ return FAILURE;
+ }
+ if (EG(exception)) {
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_index_write(
+ HashTable *ht, zend_string *offset)
+{
+ /* The array may be destroyed while throwing the notice.
+ * Temporarily increase the refcount to detect this situation. */
+ if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
+ GC_ADDREF(ht);
+ }
+ zend_undefined_index(offset);
+ if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
+ zend_array_destroy(ht);
+ return FAILURE;
+ }
+ if (EG(exception)) {
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method)
{
zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(method));
@@ -2028,9 +2066,10 @@ num_undef:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_undefined_offset(hval);
- retval = zend_hash_index_update(ht, hval, &EG(uninitialized_zval));
- break;
+ if (UNEXPECTED(zend_undefined_offset_write(ht, hval) == FAILURE)) {
+ return NULL;
+ }
+ /* break missing intentionally */
case BP_VAR_W:
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
break;
@@ -2058,7 +2097,9 @@ str_index:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_undefined_index(offset_key);
+ if (UNEXPECTED(zend_undefined_index_write(ht, offset_key))) {
+ return NULL;
+ }
/* break missing intentionally */
case BP_VAR_W:
ZVAL_NULL(retval);
@@ -2076,9 +2117,10 @@ str_index:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_undefined_index(offset_key);
- retval = zend_hash_update(ht, offset_key, &EG(uninitialized_zval));
- break;
+ if (UNEXPECTED(zend_undefined_index_write(ht, offset_key) == FAILURE)) {
+ return NULL;
+ }
+ /* break missing intentionally */
case BP_VAR_W:
retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
break;
@@ -2143,7 +2185,9 @@ fetch_from_array:
} else {
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
if (UNEXPECTED(!retval)) {
- ZVAL_UNDEF(result);
+ /* This may fail without throwing if the array was modified while throwing an
+ * undefined index error. */
+ ZVAL_NULL(result);
return;
}
}