diff options
-rw-r--r-- | Zend/zend_compile.c | 24 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 19 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 47 | ||||
-rw-r--r-- | Zend/zend_vm_handlers.h | 2 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 2 |
5 files changed, 61 insertions, 33 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2050117648..1f20c4591d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1150,12 +1150,26 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint3 while (opline_num != (uint32_t)-1) { const zend_op *opline = &op_array->opcodes[opline_num]; zval *lcname = RT_CONSTANT(opline, opline->op1); - zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname + 1)); - zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); - zend_class_entry *parent_ce = zend_lookup_class_ex(ce->parent_name, lc_parent_name, 0); + zval *zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1); - if (ce && parent_ce && zend_can_early_bind(ce, parent_ce)) { - do_bind_class(lcname, lc_parent_name); + if (zv) { + zend_class_entry *ce = Z_CE_P(zv); + zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zend_class_entry *parent_ce = zend_hash_find_ex_ptr(EG(class_table), lc_parent_name, 1); + + if (parent_ce && zend_can_early_bind(ce, parent_ce)) { + zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname)); + if (UNEXPECTED(!zv)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); + } else { + ce->ce_flags |= ZEND_ACC_LINKED; + zend_do_inheritance(ce, parent_ce); + zend_build_properties_info_table(ce); + if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) { + zend_verify_abstract_class(ce); + } + } + } } opline_num = op_array->opcodes[opline_num].result.opline_num; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index bd14092fb3..a5e888a1b4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7034,16 +7034,23 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, ANY) +ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST) { USE_OPLINE - zval *zce, *orig_zce; + zval *lcname, *zv; SAVE_OPLINE(); - if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL || - ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL && - Z_CE_P(zce) != Z_CE_P(orig_zce))) { - do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL); + lcname = RT_CONSTANT(opline, opline->op1); + zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1); + + if (zv) { + zend_class_entry *ce = Z_CE_P(zv); + zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname)); + if (UNEXPECTED(!zv)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); + } else { + zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))); + } } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4f7aa5dc07..addf769b8a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4026,20 +4026,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDL ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *zce, *orig_zce; - - SAVE_OPLINE(); - if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL || - ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL && - Z_CE_P(zce) != Z_CE_P(orig_zce))) { - do_bind_class(RT_CONSTANT(opline, opline->op1), (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6146,6 +6132,27 @@ array_key_exists_array: } /* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */ +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *lcname, *zv; + + SAVE_OPLINE(); + lcname = RT_CONSTANT(opline, opline->op1); + zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1); + + if (zv) { + zend_class_entry *ce = Z_CE_P(zv); + zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname)); + if (UNEXPECTED(!zv)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name)); + } else { + zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))); + } + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -54098,7 +54105,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_CV_LABEL, (void*)&&ZEND_DECLARE_CONST_SPEC_CONST_CONST_LABEL, - (void*)&&ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_LABEL, + (void*)&&ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -56112,10 +56119,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_DECLARE_CLASS_SPEC_CONST) ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST): - VM_TRACE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST) - ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_YIELD_FROM_SPEC_CONST): VM_TRACE(ZEND_YIELD_FROM_SPEC_CONST) ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -56340,6 +56343,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST) ZEND_ARRAY_KEY_EXISTS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST): + VM_TRACE(ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST) + ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DECLARE_CONST_SPEC_CONST_CONST): VM_TRACE(ZEND_DECLARE_CONST_SPEC_CONST_CONST) ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -63807,7 +63814,7 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_YIELD_FROM_SPEC_CV_HANDLER, ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, - ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_HANDLER, + ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index a8aae733fd..12f03bf49e 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1422,7 +1422,7 @@ _(2703, ZEND_YIELD_FROM_SPEC_VAR) \ _(2705, ZEND_YIELD_FROM_SPEC_CV) \ _(2706, ZEND_DECLARE_CONST_SPEC_CONST_CONST) \ - _(2707, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST) \ + _(2707, ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST) \ _(2758, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST) \ _(2759, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP) \ _(2760, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 70d9fbcc19..38654cf2ce 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -380,7 +380,7 @@ static uint32_t zend_vm_opcodes_flags[209] = { 0x00000003, 0x00000303, 0x00000000, - 0x00000003, + 0x00000303, 0x00000000, 0x00006701, 0x00060757, |