From: Nikita Popov Date: Mon, 12 Oct 2020 07:46:38 +0000 (+0200) Subject: Merge branch 'PHP-7.4' into PHP-8.0 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d953cd18621709f115b1cf5ba93e75769a532d9e;p=php Merge branch 'PHP-7.4' into PHP-8.0 * PHP-7.4: Avoid non-object in FE_FREE --- d953cd18621709f115b1cf5ba93e75769a532d9e diff --cc Zend/zend_vm_def.h index 930cd342e8,bc7550f4ed..d647dddeab --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -6482,24 -6316,17 +6482,20 @@@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CO FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE(); } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - if (zend_hash_num_elements(properties) == 0) { - ZEND_VM_C_GOTO(fe_reset_r_empty); - } - - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (OP1_TYPE != IS_TMP_VAR) { @@@ -6521,8 -6355,7 +6524,7 @@@ } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); - ZEND_VM_C_LABEL(fe_reset_r_empty): ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; FREE_OP1(); diff --cc Zend/zend_vm_execute.h index e180c28c75,0e65367eb5..27d1ee1571 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@@ -4791,24 -4139,17 +4791,20 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - if (zend_hash_num_elements(properties) == 0) { - goto fe_reset_r_empty; - } - - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_CONST != IS_TMP_VAR) { @@@ -4829,8 -4177,7 +4832,7 @@@ } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); - fe_reset_r_empty: ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; @@@ -18798,24 -18210,17 +18801,20 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - if (zend_hash_num_elements(properties) == 0) { - goto fe_reset_r_empty; - } - - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_TMP_VAR != IS_TMP_VAR) { @@@ -18837,11 -18249,10 +18843,10 @@@ } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); - fe_reset_r_empty: ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@@ -21357,34 -21316,34 +21363,37 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS } Z_FE_POS_P(result) = 0; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - if (zend_hash_num_elements(properties) == 0) { - goto fe_reset_r_empty; - } - - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_VAR != IS_TMP_VAR) { Z_ADDREF_P(array_ptr); } + + if (zend_hash_num_elements(properties) == 0) { + Z_FE_ITER_P(result) = (uint32_t) -1; - zval_ptr_dtor_nogc(free_op1); ++ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { zend_bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC); @@@ -21399,11 -21358,10 +21408,10 @@@ } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); - fe_reset_r_empty: ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1; - zval_ptr_dtor_nogc(free_op1); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } } @@@ -21473,6 -21432,7 +21481,7 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS properties = Z_OBJPROP_P(array_ptr); if (zend_hash_num_elements(properties) == 0) { Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1; - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; ++ zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } @@@ -38072,24 -37846,17 +38081,20 @@@ static ZEND_OPCODE_HANDLER_RET ZEND_FAS ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) { - if (!Z_OBJCE_P(array_ptr)->get_iterator) { - HashTable *properties; - if (Z_OBJ_P(array_ptr)->properties - && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_DELREF(Z_OBJ_P(array_ptr)->properties); + zend_object *zobj = Z_OBJ_P(array_ptr); + if (!zobj->ce->get_iterator) { + HashTable *properties = zobj->properties; + if (properties) { + if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) { + GC_DELREF(properties); + } + properties = zobj->properties = zend_array_dup(properties); } - Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); + } else { + properties = zobj->handlers->get_properties(zobj); } - if (zend_hash_num_elements(properties) == 0) { - goto fe_reset_r_empty; - } - - properties = Z_OBJPROP_P(array_ptr); result = EX_VAR(opline->result.var); ZVAL_COPY_VALUE(result, array_ptr); if (IS_CV != IS_TMP_VAR) { @@@ -38110,8 -37884,7 +38122,7 @@@ } } } else { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_type_name(array_ptr)); - fe_reset_r_empty: ZVAL_UNDEF(EX_VAR(opline->result.var)); Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;