--- /dev/null
+--TEST--
+Converting undefined index/offset notice to exception
+--FILE--
+<?php
+
+set_error_handler(function($_, $msg) {
+ throw new Exception($msg);
+});
+
+$test = [];
+try {
+ $test[0] .= "xyz";
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($test);
+
+try {
+ $test["key"] .= "xyz";
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($test);
+
+unset($test);
+try {
+ $GLOBALS["test"] .= "xyz";
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump($test);
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+Undefined offset: 0
+array(0) {
+}
+Undefined index: key
+array(0) {
+}
+Undefined index: test
+Undefined variable: test
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));
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;
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);
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;