@@ -1183,6 +1183,9 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
11831183
11841184 value = get_op_data_zval_ptr_r ((opline + 1 )-> op1_type , (opline + 1 )-> op1 );
11851185
1186+ /* Prevents array from being released or updated during binary_op */
1187+ GC_ADDREF (ht );
1188+
11861189 do {
11871190 if (OP2_TYPE != IS_UNUSED && UNEXPECTED (Z_ISREF_P (var_ptr ))) {
11881191 zend_reference * ref = Z_REF_P (var_ptr );
@@ -1198,6 +1201,9 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
11981201 if (UNEXPECTED (RETURN_VALUE_USED (opline ))) {
11991202 ZVAL_COPY (EX_VAR (opline -> result .var ), var_ptr );
12001203 }
1204+
1205+ GC_DTOR (ht );
1206+
12011207 FREE_OP ((opline + 1 )-> op1_type , (opline + 1 )-> op1 .var );
12021208 } else {
12031209 if (EXPECTED (Z_ISREF_P (container ))) {
@@ -1259,22 +1265,45 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP)
12591265 value = GET_OP2_ZVAL_PTR (BP_VAR_R );
12601266 var_ptr = GET_OP1_ZVAL_PTR_PTR (BP_VAR_RW );
12611267
1262- do {
1263- if (UNEXPECTED (Z_TYPE_P (var_ptr ) == IS_REFERENCE )) {
1264- zend_reference * ref = Z_REF_P (var_ptr );
1265- var_ptr = Z_REFVAL_P (var_ptr );
1266- if (UNEXPECTED (ZEND_REF_HAS_TYPE_SOURCES (ref ))) {
1267- zend_binary_assign_op_typed_ref (ref , value OPLINE_CC EXECUTE_DATA_CC );
1268- break ;
1268+ if (UNEXPECTED (Z_TYPE_P (var_ptr ) == IS_REFERENCE )) {
1269+ ZEND_VM_C_LABEL (assign_op_ref ):
1270+ zend_reference * ref = Z_REF_P (var_ptr );
1271+ GC_ADDREF (ref );
1272+
1273+ var_ptr = Z_REFVAL_P (var_ptr );
1274+ if (UNEXPECTED (ZEND_REF_HAS_TYPE_SOURCES (ref ))) {
1275+ zend_binary_assign_op_typed_ref (ref , value OPLINE_CC EXECUTE_DATA_CC );
1276+ } else {
1277+ zend_binary_op (var_ptr , var_ptr , value OPLINE_CC );
1278+ }
1279+
1280+ if (UNEXPECTED (GC_DELREF (ref ) == 0 )) {
1281+ if (RETURN_VALUE_USED (opline )) {
1282+ ZVAL_COPY_VALUE (EX_VAR (opline -> result .var ), var_ptr );
1283+ var_ptr = EX_VAR (opline -> result .var );
1284+ } else {
1285+ zval_ptr_dtor (var_ptr );
12691286 }
1287+ efree_size (ref , sizeof (zend_reference ));
1288+ ZEND_VM_C_GOTO (assign_op_end );
1289+ }
1290+ } else {
1291+ if (OP1_TYPE == IS_VAR ) {
1292+ ZEND_ASSERT (Z_TYPE_P (EX_VAR (opline -> op1 .num )) == IS_INDIRECT );
1293+ /* op1 is a var-var, var_ptr is a symbol table slot which may be
1294+ * invalidated by the binary operation. Turn it into a ref so we
1295+ * control the lifetime of the zval slot. */
1296+ ZVAL_MAKE_REF (var_ptr );
1297+ ZEND_VM_C_GOTO (assign_op_ref );
12701298 }
12711299 zend_binary_op (var_ptr , var_ptr , value OPLINE_CC );
1272- } while ( 0 );
1300+ }
12731301
12741302 if (UNEXPECTED (RETURN_VALUE_USED (opline ))) {
12751303 ZVAL_COPY (EX_VAR (opline -> result .var ), var_ptr );
12761304 }
12771305
1306+ ZEND_VM_C_LABEL (assign_op_end ):
12781307 FREE_OP2 ();
12791308 FREE_OP1 ();
12801309 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION ();
0 commit comments