Optimized ASSIGN_DIM and related opcodes
authorDmitry Stogov <dmitry@zend.com>
Tue, 21 Oct 2014 15:30:43 +0000 (19:30 +0400)
committerDmitry Stogov <dmitry@zend.com>
Tue, 21 Oct 2014 15:30:43 +0000 (19:30 +0400)
Zend/zend_compile.c
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 5d3ee24c84faa38c9192a514e0cbcd0ba867bb63..a8bfdb1a40b8bc0275f222d34206dbdaba50ed49 100644 (file)
@@ -2281,8 +2281,6 @@ void zend_compile_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
                        opline->opcode = ZEND_ASSIGN_DIM;
 
                        opline = zend_emit_op_data(&expr_node TSRMLS_CC);
-                       opline->op2.var = get_temporary_variable(CG(active_op_array));
-                       opline->op2_type = IS_VAR;
                        return;
                case ZEND_AST_PROP:
                        offset = zend_delayed_compile_begin(TSRMLS_C);
@@ -2374,8 +2372,6 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast TSRMLS_DC) /* {{{
                        opline->extended_value = ZEND_ASSIGN_DIM;
 
                        opline = zend_emit_op_data(&expr_node TSRMLS_CC);
-                       opline->op2.var = get_temporary_variable(CG(active_op_array));
-                       opline->op2_type = IS_VAR;
                        return;
                case ZEND_AST_PROP:
                        offset = zend_delayed_compile_begin(TSRMLS_C);
index 58038c94a4cd83c442368ada8e0ba91581a025c8..7c6deca6c83345f2ca12979595d35beccc46acb3 100644 (file)
@@ -1048,12 +1048,61 @@ str_index:
        return retval;
 }
 
-static zend_always_inline zval *zend_fetch_dimension_address(zval *result, zval *container_ptr, zval *dim, int dim_type, int type, int is_ref, int allow_str_offset TSRMLS_DC)
+static zend_never_inline zend_long zend_check_string_offset(zval *container, zval *dim, int type TSRMLS_DC)
+{
+       zend_long offset;
+
+       if (dim == NULL) {
+               zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
+       }
+
+       if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
+               switch(Z_TYPE_P(dim)) {
+                       case IS_STRING:
+                               if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
+                                       break;
+                               }
+                               if (type != BP_VAR_UNSET) {
+                                       zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
+                               }
+                               break;
+                       case IS_DOUBLE:
+                       case IS_NULL:
+                       case IS_FALSE:
+                       case IS_TRUE:
+                               zend_error(E_NOTICE, "String offset cast occurred");
+                               break;
+                       default:
+                               zend_error(E_WARNING, "Illegal offset type");
+                               break;
+               }
+
+               offset = zval_get_long(dim);
+       } else {
+               offset = Z_LVAL_P(dim);
+       }
+
+       return offset;
+}
+
+static zend_always_inline zend_long zend_fetch_string_offset(zval *container, zval *dim, int type TSRMLS_DC)
+{
+       zend_long offset = zend_check_string_offset(container, dim, type TSRMLS_CC);
+
+       if (Z_REFCOUNTED_P(container)) {
+               if (Z_REFCOUNT_P(container) > 1) {
+                       Z_DELREF_P(container);
+                       zval_copy_ctor_func(container);
+               }
+               Z_ADDREF_P(container);
+       }
+       return offset;
+}
+
+static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type, int is_ref TSRMLS_DC)
 {
     zval *retval;
-    zval *container = container_ptr;
 
-       ZVAL_DEREF(container);
        if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
                SEPARATE_ARRAY(container);
 fetch_from_array:
@@ -1071,8 +1120,6 @@ fetch_from_array:
                }
                ZVAL_INDIRECT(result, retval);
        } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
-               zend_long offset;
-
                if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
                        zval_ptr_dtor_nogc(container);
 convert_to_array:
@@ -1081,49 +1128,9 @@ convert_to_array:
                        goto fetch_from_array;
                }
 
-               if (dim == NULL) {
-                       zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
-               }
-
-               if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
-                       switch(Z_TYPE_P(dim)) {
-                               case IS_STRING:
-                                       if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
-                                               break;
-                                       }
-                                       if (type != BP_VAR_UNSET) {
-                                               zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
-                                       }
-                                       break;
-                               case IS_DOUBLE:
-                               case IS_NULL:
-                               case IS_FALSE:
-                               case IS_TRUE:
-                                       zend_error(E_NOTICE, "String offset cast occurred");
-                                       break;
-                               default:
-                                       zend_error(E_WARNING, "Illegal offset type");
-                                       break;
-                       }
-
-                       offset = zval_get_long(dim);
-               } else {
-                       offset = Z_LVAL_P(dim);
-               }
-
-               if (allow_str_offset) {
-                       if (Z_REFCOUNTED_P(container)) {
-                               if (Z_REFCOUNT_P(container) > 1) {
-                                       Z_DELREF_P(container);
-                                       zval_copy_ctor_func(container);
-                               }
-                               Z_ADDREF_P(container);
-                       }
-                       ZVAL_LONG(result, offset);
-                       return container; /* assignment to string offset */
-               } else {
-                       ZVAL_INDIRECT(result, NULL); /* wrong string offset */
-               }
+               zend_check_string_offset(container, dim, type TSRMLS_CC);
+               
+               ZVAL_INDIRECT(result, NULL); /* wrong string offset */
        } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (!Z_OBJ_HT_P(container)->read_dimension) {
                        zend_error_noreturn(E_ERROR, "Cannot use object as array");
@@ -1185,32 +1192,26 @@ convert_to_array:
                        ZVAL_INDIRECT(result, &EG(error_zval));
                }
        }
-       return NULL; /* not an assignment to string offset */
 }
 
 static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
 {
-       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 0 TSRMLS_CC);
-}
-
-static zend_never_inline zval *zend_fetch_dimension_address_W_str(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
-{
-       return zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0, 1 TSRMLS_CC);
+       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 0 TSRMLS_CC);
 }
 
 static zend_never_inline void zend_fetch_dimension_address_W_ref(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
 {
-       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1, 0 TSRMLS_CC);
+       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W, 1 TSRMLS_CC);
 }
 
 static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
 {
-       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0, 0 TSRMLS_CC);
+       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW, 0 TSRMLS_CC);
 }
 
 static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type TSRMLS_DC)
 {
-       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0, 0 TSRMLS_CC);
+       zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET, 0 TSRMLS_CC);
 }
 
 static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
index 0c5ef75be43b145fe66bf989a1c39de64c48dc90..f41365b61581fc7efb63ca461e1fb547f9649bbf 100644 (file)
@@ -423,15 +423,19 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
 ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNUSED|CV, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC))
 {
        USE_OPLINE
-       zend_free_op free_op1, free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op1, free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
        if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (OP1_TYPE == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (OP1_TYPE != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (OP1_TYPE == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (OP1_TYPE == IS_VAR && !OP1_FREE) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -439,9 +443,10 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR
        } else {
                zval *dim = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, OP2_TYPE TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, OP2_TYPE TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -465,7 +470,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMP|VAR
 
        FREE_OP2();
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
        FREE_OP1_VAR_PTR();
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -1195,6 +1199,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
        if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
        } else {
@@ -1221,6 +1226,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
        if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
        FREE_OP2();
        if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -1262,6 +1268,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNU
                if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
                if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -1293,6 +1300,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
        if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
        FREE_OP2();
        if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -1549,19 +1557,25 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, OP1_TYPE, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
                FREE_OP2();
        } else {
-               zend_free_op free_op2, free_op_data1, free_op_data2;
+               zend_free_op free_op2, free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, OP2_TYPE TSRMLS_CC);
-               FREE_OP2();
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
+                       FREE_OP2();
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, OP2_TYPE TSRMLS_CC);
+                       FREE_OP2();
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -1575,7 +1589,6 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
index 14f2d6ebb58dbac23aef196709ebb165b4fee8d4..fe443f87b3b5dfba07b51c8ab752257a2c7fd7fb 100644 (file)
@@ -3931,6 +3931,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_
                if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
                if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -5275,6 +5276,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OP
                if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
                if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -6469,6 +6471,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OP
                if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
                if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -7503,6 +7506,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND
                if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
                if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -8386,6 +8390,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPC
                if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
                if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -10734,6 +10739,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OP
                if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
                if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -11917,6 +11923,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCO
                if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
                if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -13084,6 +13091,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCO
                if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
                if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -14092,6 +14100,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_O
                if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
                if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -14827,6 +14836,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCOD
                if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
                if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -17561,15 +17571,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op1, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op1, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_VAR != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -17577,9 +17591,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b
        } else {
                zval *dim = opline->op2.zv;
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -17602,7 +17617,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*b
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
        if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -18139,6 +18153,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
        } else {
@@ -18165,6 +18180,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -18206,6 +18222,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP
                if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
                if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -18237,6 +18254,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -18491,19 +18509,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
 
        } else {
-               zend_free_op free_op_data1, free_op_data2;
+               zend_free_op free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = opline->op2.zv;
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
 
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC);
+
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -18517,7 +18541,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -19949,15 +19972,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op1, free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op1, free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_VAR != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -19965,9 +19992,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin
        } else {
                zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -19991,7 +20019,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMP(int (*bin
 
        zval_ptr_dtor_nogc(free_op2.var);
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
        if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -20380,6 +20407,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
        } else {
@@ -20406,6 +20434,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -20447,6 +20476,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO
                if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
                if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -20478,6 +20508,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -20701,19 +20732,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
                zval_ptr_dtor_nogc(free_op2.var);
        } else {
-               zend_free_op free_op2, free_op_data1, free_op_data2;
+               zend_free_op free_op2, free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
-               zval_ptr_dtor_nogc(free_op2.var);
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -20727,7 +20764,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -21921,15 +21957,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op1, free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op1, free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_VAR != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -21937,9 +21977,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin
        } else {
                zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -21963,7 +22004,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_VAR(int (*bin
 
        zval_ptr_dtor_nogc(free_op2.var);
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
        if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -22503,6 +22543,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
        } else {
@@ -22529,6 +22570,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -22570,6 +22612,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO
                if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
                if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -22601,6 +22644,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -22824,19 +22868,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
                zval_ptr_dtor_nogc(free_op2.var);
        } else {
-               zend_free_op free_op2, free_op_data1, free_op_data2;
+               zend_free_op free_op2, free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC);
-               zval_ptr_dtor_nogc(free_op2.var);
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -22850,7 +22900,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -23978,15 +24027,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op1, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op1, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_VAR != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -23994,9 +24047,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*
        } else {
                zval *dim = NULL;
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -24019,7 +24073,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
        if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -24367,6 +24420,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
        } else {
@@ -24393,6 +24447,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -24419,6 +24474,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O
                if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
                if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -24458,19 +24514,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
 
        } else {
-               zend_free_op free_op_data1, free_op_data2;
+               zend_free_op free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = NULL;
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
 
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC);
+
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -24484,7 +24546,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -25409,15 +25470,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op1, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op1, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_VAR != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -25425,9 +25490,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina
        } else {
                zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -25450,7 +25516,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*bina
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
        if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);};
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -25836,6 +25901,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
        } else {
@@ -25862,6 +25928,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -25903,6 +25970,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD
                if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
                if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -25934,6 +26002,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H
        if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -26155,19 +26224,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_VAR, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
 
        } else {
-               zend_free_op free_op_data1, free_op_data2;
+               zend_free_op free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
 
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC);
+
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -26181,7 +26256,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -27236,15 +27310,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC);
        if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_UNUSED != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_UNUSED == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -27252,9 +27330,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int
        } else {
                zval *dim = opline->op2.zv;
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -27277,7 +27356,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -28587,15 +28665,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC);
        if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_UNUSED != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_UNUSED == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -28603,9 +28685,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*
        } else {
                zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -28629,7 +28712,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMP(int (*
 
        zval_ptr_dtor_nogc(free_op2.var);
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -29857,15 +29939,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC);
        if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_UNUSED != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_UNUSED == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -29873,9 +29959,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*
        } else {
                zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -29899,7 +29986,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_VAR(int (*
 
        zval_ptr_dtor_nogc(free_op2.var);
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -31126,15 +31212,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC);
        if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_UNUSED != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_UNUSED == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -31142,9 +31232,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int
        } else {
                zval *dim = NULL;
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -31167,7 +31258,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -31613,15 +31703,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_obj_zval_ptr_unused(execute_data TSRMLS_CC);
        if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_UNUSED != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_UNUSED == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -31629,9 +31723,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b
        } else {
                zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -31654,7 +31749,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*b
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -34548,15 +34642,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_CV != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_CV == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -34564,9 +34662,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi
        } else {
                zval *dim = opline->op2.zv;
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CONST TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -34589,7 +34688,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*bi
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -35126,6 +35224,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
        } else {
@@ -35152,6 +35251,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
 
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -35193,6 +35293,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC
                if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
                if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -35224,6 +35325,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC);
 
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -35478,19 +35580,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
 
        } else {
-               zend_free_op free_op_data1, free_op_data2;
+               zend_free_op free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = opline->op2.zv;
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CONST TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
 
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST TSRMLS_CC);
+
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -35504,7 +35612,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -36768,15 +36875,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_CV != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_CV == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -36784,9 +36895,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina
        } else {
                zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_TMP_VAR TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_TMP_VAR TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -36810,7 +36922,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMP(int (*bina
 
        zval_ptr_dtor_nogc(free_op2.var);
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -37199,6 +37310,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
        } else {
@@ -37225,6 +37337,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -37266,6 +37379,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD
                if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
                if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -37297,6 +37411,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -37520,19 +37635,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
                zval_ptr_dtor_nogc(free_op2.var);
        } else {
-               zend_free_op free_op2, free_op_data1, free_op_data2;
+               zend_free_op free_op2, free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
-               zval_ptr_dtor_nogc(free_op2.var);
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_TMP_VAR TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -37546,7 +37667,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -38612,15 +38732,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op2, free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op2, free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_CV != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_CV == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -38628,9 +38752,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina
        } else {
                zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_VAR TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_VAR TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -38654,7 +38779,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_VAR(int (*bina
 
        zval_ptr_dtor_nogc(free_op2.var);
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -39194,6 +39318,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
        } else {
@@ -39220,6 +39345,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -39261,6 +39387,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD
                if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
                if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -39292,6 +39419,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC);
        zval_ptr_dtor_nogc(free_op2.var);
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -39515,19 +39643,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
                zval_ptr_dtor_nogc(free_op2.var);
        } else {
-               zend_free_op free_op2, free_op_data1, free_op_data2;
+               zend_free_op free_op2, free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_VAR TSRMLS_CC);
-               zval_ptr_dtor_nogc(free_op2.var);
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_VAR TSRMLS_CC);
+                       zval_ptr_dtor_nogc(free_op2.var);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -39541,7 +39675,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -40539,15 +40672,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_CV != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_CV == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -40555,9 +40692,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b
        } else {
                zval *dim = NULL;
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_UNUSED TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -40580,7 +40718,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*b
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -40928,6 +41065,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
        } else {
@@ -40954,6 +41092,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
 
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -40980,6 +41119,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP
                if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC);
                if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -41019,19 +41159,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
 
        } else {
-               zend_free_op free_op_data1, free_op_data2;
+               zend_free_op free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = NULL;
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_UNUSED TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
 
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED TSRMLS_CC);
+
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -41045,7 +41191,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }
@@ -41825,15 +41970,19 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
 static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_free_op free_op_data2, free_op_data1;
-       zval *var_ptr;
+       zend_free_op free_op_data1;
+       zval *var_ptr, rv;
        zval *value, *container;
 
        SAVE_OPLINE();
        container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC);
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
-       } else if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+       }
+       if (IS_CV != IS_UNUSED) {
+               ZVAL_DEREF(container);
+       }
+       if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
                if (IS_CV == IS_VAR && !0) {
                        Z_ADDREF_P(container);  /* undo the effect of get_obj_zval_ptr_ptr() */
                }
@@ -41841,9 +41990,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar
        } else {
                zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
 
-               zend_fetch_dimension_address_RW(EX_VAR((opline+1)->op2.var), container, dim, IS_CV TSRMLS_CC);
+               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV TSRMLS_CC);
                value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+               ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+               var_ptr = Z_INDIRECT(rv);
        }
 
        if (UNEXPECTED(var_ptr == NULL)) {
@@ -41866,7 +42016,6 @@ static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binar
        }
 
        FREE_OP(free_op_data1);
-       FREE_OP_VAR_PTR(free_op_data2);
 
        CHECK_EXCEPTION();
        ZEND_VM_INC_OPCODE();
@@ -42252,6 +42401,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        if (EXPECTED(opline->extended_value == 0)) {
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
        } else {
@@ -42278,6 +42428,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
 
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -42319,6 +42470,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE
                if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
                }
+               ZVAL_DEREF(container);
                zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
                if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
                        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
@@ -42350,6 +42502,7 @@ static int ZEND_FASTCALL  ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA
        if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
+       ZVAL_DEREF(container);
        zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC);
 
        if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
@@ -42571,19 +42724,25 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
                zend_assign_to_object(RETURN_VALUE_USED(opline)?EX_VAR(opline->result.var):NULL, object_ptr, IS_CV, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property_name)) : NULL) TSRMLS_CC);
 
        } else {
-               zend_free_op free_op_data1, free_op_data2;
+               zend_free_op free_op_data1;
+               zval  rv;
                zval *value;
                zval *dim = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
                zval *variable_ptr;
 
-               variable_ptr = zend_fetch_dimension_address_W_str(EX_VAR((opline+1)->op2.var), object_ptr, dim, IS_CV TSRMLS_CC);
+               if (UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
+                   EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+                       zend_long offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W TSRMLS_CC);
 
-               value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
-               if (UNEXPECTED(variable_ptr != NULL)) {
-                       zend_assign_to_string_offset(variable_ptr, Z_LVAL_P(EX_VAR((opline+1)->op2.var)), value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       zend_assign_to_string_offset(object_ptr, offset, value, (RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : NULL) TSRMLS_CC);
                        FREE_OP(free_op_data1);
                } else {
-                       variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
+                       zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV TSRMLS_CC);
+
+                       value = get_zval_ptr_deref((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
+                       variable_ptr = Z_INDIRECT(rv);
                        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                                FREE_OP(free_op_data1);
                                if (RETURN_VALUE_USED(opline)) {
@@ -42597,7 +42756,6 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_COPY(EX_VAR(opline->result.var), value);
                                }
-                               FREE_OP_VAR_PTR(free_op_data2);
                        }
                }
        }