From 15443f8af4783ce6ea5362ec5a38a62b69ff8447 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 9 Oct 2020 16:56:08 +0200 Subject: Fixed bug #80186 Early exit in FE_RESET if get_properties() returns empty array, as we cannot add HT iterators to zend_empty_array. --- Zend/zend_vm_def.h | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'Zend/zend_vm_def.h') diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 40b20f0d9c..6305ef8ef4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6317,11 +6317,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) 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) { - result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, array_ptr); - if (OP1_TYPE != IS_TMP_VAR) { - Z_ADDREF_P(array_ptr); - } + 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))) { @@ -6329,8 +6325,18 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) } Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + properties = Z_OBJPROP_P(array_ptr); + if (zend_hash_num_elements(properties) == 0) { + ZEND_VM_C_GOTO(fe_reset_r_empty); + } + + result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, array_ptr); + if (OP1_TYPE != IS_TMP_VAR) { + Z_ADDREF_P(array_ptr); + } + Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0); FREE_OP1_IF_VAR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { @@ -6347,6 +6353,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR) } } else { zend_error(E_WARNING, "Invalid argument supplied for foreach()"); +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(); @@ -6397,6 +6404,7 @@ ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR) 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 (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) { if (array_ptr == array_ref) { ZVAL_NEW_REF(array_ref, array_ref); @@ -6415,8 +6423,14 @@ ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR) } Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties); } - Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_OBJPROP_P(array_ptr), 0); + 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; + ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); + } + + Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0); FREE_OP1_VAR_PTR(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } else { -- cgit v1.2.1