@@ -2732,14 +2732,18 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
27322732 } else {
27332733 HashTable * ht = Z_ARRVAL_P (object_ptr );
27342734 dim = GET_OP2_ZVAL_PTR_UNDEF (BP_VAR_R );
2735+ /* Order is critical: fetch the data value (which may emit an
2736+ * "Undefined variable" warning that can recurse into user code
2737+ * via a user output handler) before resolving variable_ptr.
2738+ * Resolving variable_ptr only afterwards guarantees a fresh
2739+ * bucket pointer that cannot have been invalidated by user
2740+ * code freeing the array, rehashing it, or unsetting keys. */
27352741 value = GET_OP_DATA_ZVAL_PTR_UNDEF (BP_VAR_R );
27362742 if (OP_DATA_TYPE == IS_CV && UNEXPECTED (Z_TYPE_P (value ) == IS_UNDEF )) {
2737- /* The undefined-variable warning may recurse into user code
2738- * (e.g. a user output handler) and clobber or destroy the
2739- * array we are about to write to. Temporarily addref the
2740- * array to detect destruction, and refetch the dim address
2741- * after the warning since the previous variable_ptr may have
2742- * been invalidated by hash table mutations. */
2743+ /* Temporarily addref the array around the warning so we
2744+ * can detect a full destruction (last ref dropped by
2745+ * reentrant user code) and bail out cleanly. Mirrors the
2746+ * IS_UNUSED branch above. */
27432747 if (!(GC_FLAGS (ht ) & IS_ARRAY_IMMUTABLE )) {
27442748 GC_ADDREF (ht );
27452749 }
0 commit comments