]> granicus.if.org Git - php/commitdiff
Fixed string offset handling
authorDmitry Stogov <dmitry@zend.com>
Thu, 6 Mar 2014 12:00:38 +0000 (16:00 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 6 Mar 2014 12:00:38 +0000 (16:00 +0400)
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index e3c25db4f4fec4e2085fa526089ee7bc56e9303d..7b604493e37563d12d98a17ec763a841f11cec10 100644 (file)
@@ -1661,7 +1661,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
        if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -1689,7 +1689,8 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -1697,7 +1698,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -1741,7 +1742,8 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
        variable_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
 
        if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, OP2_TYPE TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, OP2_TYPE TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -1749,7 +1751,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of FREE_OP1_VAR_PTR()
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (IS_OP2_TMP_FREE()) {
index b9b3aad21cb95096354a19bcc0d8173b8947f06e..8d01ddf79feda0139a57f52782539ddd27c72265 100644 (file)
@@ -15075,7 +15075,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -15102,7 +15102,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -15110,7 +15111,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -15154,7 +15155,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER
        variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_CONST TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_CONST TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -15162,7 +15164,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (0) {
@@ -17393,7 +17395,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -17421,7 +17423,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -17429,7 +17432,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -17473,7 +17476,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
        variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -17481,7 +17485,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (1) {
@@ -19608,7 +19612,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -19636,7 +19640,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -19644,7 +19649,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -19688,7 +19693,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
        variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_VAR TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_VAR TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -19696,7 +19702,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (0) {
@@ -21213,7 +21219,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -21240,7 +21246,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -21248,7 +21255,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -23019,7 +23026,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -23046,7 +23053,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -23054,7 +23062,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -23098,7 +23106,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
        variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC);
 
        if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_CV TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_CV TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -23106,7 +23115,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of if (free_op1.var) {zval_ptr_dtor_nogc(free_op1.var);}
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (0) {
@@ -32303,7 +32312,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -32330,7 +32339,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -32338,7 +32348,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -32382,7 +32392,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_
        variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
 
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_CONST TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_CONST TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -32390,7 +32401,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (0) {
@@ -34403,7 +34414,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -34431,7 +34442,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -34439,7 +34451,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -34483,7 +34495,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
        variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
 
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_TMP_VAR TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -34491,7 +34504,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (1) {
@@ -36493,7 +36506,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -36521,7 +36534,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -36529,7 +36543,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -36573,7 +36587,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
        variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
 
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_VAR TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_VAR TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -36581,7 +36596,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (0) {
@@ -37976,7 +37991,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -38003,7 +38018,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -38011,7 +38027,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -39644,7 +39660,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(object_ptr) == IS_STR_OFFSET)) {
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
        }
-       if (Z_TYPE_P(object_ptr) == IS_REFERENCE) {
+       if (Z_TYPE_P(object_ptr) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(object_ptr)) == IS_OBJECT) {
                object_ptr = Z_REFVAL_P(object_ptr);
        }
        if (Z_TYPE_P(object_ptr) == IS_OBJECT) {
@@ -39671,7 +39687,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
                value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
                variable_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC);
                if (UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-                       if (zend_assign_to_string_offset(EX_VAR((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) {
+                       zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+                       if (zend_assign_to_string_offset(variable_ptr, value, (opline+1)->op1_type TSRMLS_CC)) {
                                if (RETURN_VALUE_USED(opline)) {
                                        ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->str) + Z_STR_OFFSET_P(EX_VAR((opline+1)->op2.var))->offset, 1);
                                }
@@ -39679,7 +39696,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER
                                ZVAL_NULL(EX_VAR(opline->result.var));
                        }
 //??? instead of FREE_OP_VAR_PTR(free_op_data2);
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+                       STR_RELEASE(old_str);
                        efree(Z_STR_OFFSET_P(variable_ptr));
                } else if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
                        if (IS_TMP_FREE(free_op_data1)) {
@@ -39723,7 +39740,8 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
        variable_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC);
 
        if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(variable_ptr) == IS_STR_OFFSET)) {
-               if (zend_assign_to_string_offset(EX_VAR(opline->op1.var), value, IS_CV TSRMLS_CC)) {
+               zend_string *old_str = Z_STR_P(Z_STR_OFFSET_P(variable_ptr)->str);
+               if (zend_assign_to_string_offset(variable_ptr, value, IS_CV TSRMLS_CC)) {
                        if (RETURN_VALUE_USED(opline)) {
                                ZVAL_STRINGL(EX_VAR(opline->result.var), Z_STRVAL_P(Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->str) + Z_STR_OFFSET_P(EX_VAR(opline->op1.var))->offset, 1);
                        }
@@ -39731,7 +39749,7 @@ static int ZEND_FASTCALL  ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
                        ZVAL_NULL(EX_VAR(opline->result.var));
                }
 //??? instead of
-//???          zval_ptr_dtor(Z_STR_OFFSET_P(variable_ptr)->str);
+               STR_RELEASE(old_str);
                efree(Z_STR_OFFSET_P(variable_ptr));
        } else if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
                if (0) {