diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-07-07 12:17:11 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-07-07 12:28:35 +0200 |
commit | 2c73bf7e3fc470e8e50cc7283844c9b1d7c2a9d2 (patch) | |
tree | 8e1f2746f4ee9fd761804f3a8bd73085eb0774f3 /Zend/zend_execute.c | |
parent | ecf368b8f2b9d578f3f9bb23f48d5920adbdccbb (diff) | |
parent | 220880ad2d54d10173a250637478da213b1ae8e2 (diff) | |
download | php-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.c | 60 |
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; } } |