@@ -1909,6 +1909,44 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_index(const
1909
1909
zend_error (E_NOTICE , "Undefined index: %s" , ZSTR_VAL (offset ));
1910
1910
}
1911
1911
1912
+ static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_offset_write (
1913
+ HashTable * ht , zend_long lval )
1914
+ {
1915
+ /* The array may be destroyed while throwing the notice.
1916
+ * Temporarily increase the refcount to detect this situation. */
1917
+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE )) {
1918
+ GC_ADDREF (ht );
1919
+ }
1920
+ zend_undefined_offset (lval );
1921
+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE ) && !GC_DELREF (ht )) {
1922
+ zend_array_destroy (ht );
1923
+ return FAILURE ;
1924
+ }
1925
+ if (EG (exception )) {
1926
+ return FAILURE ;
1927
+ }
1928
+ return SUCCESS ;
1929
+ }
1930
+
1931
+ static zend_never_inline ZEND_COLD int ZEND_FASTCALL zend_undefined_index_write (
1932
+ HashTable * ht , zend_string * offset )
1933
+ {
1934
+ /* The array may be destroyed while throwing the notice.
1935
+ * Temporarily increase the refcount to detect this situation. */
1936
+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE )) {
1937
+ GC_ADDREF (ht );
1938
+ }
1939
+ zend_undefined_index (offset );
1940
+ if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE ) && !GC_DELREF (ht )) {
1941
+ zend_array_destroy (ht );
1942
+ return FAILURE ;
1943
+ }
1944
+ if (EG (exception )) {
1945
+ return FAILURE ;
1946
+ }
1947
+ return SUCCESS ;
1948
+ }
1949
+
1912
1950
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method (const zend_class_entry * ce , const zend_string * method )
1913
1951
{
1914
1952
zend_throw_error (NULL , "Call to undefined method %s::%s()" , ZSTR_VAL (ce -> name ), ZSTR_VAL (method ));
@@ -2028,9 +2066,10 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
2028
2066
retval = & EG (uninitialized_zval );
2029
2067
break ;
2030
2068
case BP_VAR_RW :
2031
- zend_undefined_offset (hval );
2032
- retval = zend_hash_index_update (ht , hval , & EG (uninitialized_zval ));
2033
- break ;
2069
+ if (UNEXPECTED (zend_undefined_offset_write (ht , hval ) == FAILURE )) {
2070
+ return NULL ;
2071
+ }
2072
+ /* break missing intentionally */
2034
2073
case BP_VAR_W :
2035
2074
retval = zend_hash_index_add_new (ht , hval , & EG (uninitialized_zval ));
2036
2075
break ;
@@ -2058,7 +2097,9 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
2058
2097
retval = & EG (uninitialized_zval );
2059
2098
break ;
2060
2099
case BP_VAR_RW :
2061
- zend_undefined_index (offset_key );
2100
+ if (UNEXPECTED (zend_undefined_index_write (ht , offset_key ))) {
2101
+ return NULL ;
2102
+ }
2062
2103
/* break missing intentionally */
2063
2104
case BP_VAR_W :
2064
2105
ZVAL_NULL (retval );
@@ -2076,9 +2117,10 @@ static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht
2076
2117
retval = & EG (uninitialized_zval );
2077
2118
break ;
2078
2119
case BP_VAR_RW :
2079
- zend_undefined_index (offset_key );
2080
- retval = zend_hash_update (ht , offset_key , & EG (uninitialized_zval ));
2081
- break ;
2120
+ if (UNEXPECTED (zend_undefined_index_write (ht , offset_key ) == FAILURE )) {
2121
+ return NULL ;
2122
+ }
2123
+ /* break missing intentionally */
2082
2124
case BP_VAR_W :
2083
2125
retval = zend_hash_add_new (ht , offset_key , & EG (uninitialized_zval ));
2084
2126
break ;
@@ -2143,7 +2185,9 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
2143
2185
} else {
2144
2186
retval = zend_fetch_dimension_address_inner (Z_ARRVAL_P (container ), dim , dim_type , type EXECUTE_DATA_CC );
2145
2187
if (UNEXPECTED (!retval )) {
2146
- ZVAL_UNDEF (result );
2188
+ /* This may fail without throwing if the array was modified while throwing an
2189
+ * undefined index error. */
2190
+ ZVAL_NULL (result );
2147
2191
return ;
2148
2192
}
2149
2193
}
0 commit comments