diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d0f7c1d17b6..09e58aa98ae 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1100,6 +1100,32 @@ ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname) /* {{{ } /* }}} */ +ZEND_API zend_class_entry *zend_bind_class_in_slot( + zval *class_table_slot, zval *lcname, zend_string *lc_parent_name) +{ + zend_class_entry *ce = Z_PTR_P(class_table_slot); + zval *zv = zend_hash_set_bucket_key( + EG(class_table), (Bucket *) class_table_slot, 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)); + return NULL; + } + + if (ce->ce_flags & ZEND_ACC_LINKED) { + return ce; + } + + ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname)); + if (ce) { + return ce; + } + + /* Reload bucket pointer, the hash table may have been reallocated */ + zv = zend_hash_find(EG(class_table), Z_STR_P(lcname)); + zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1)); + return NULL; +} + ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */ { zend_class_entry *ce; @@ -1131,26 +1157,7 @@ ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name) /* } /* Register the derived class */ - ce = (zend_class_entry*)Z_PTR_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)); - return FAILURE; - } - - if (ce->ce_flags & ZEND_ACC_LINKED) { - return SUCCESS; - } - - ce = zend_do_link_class(ce, lc_parent_name, Z_STR_P(lcname)); - if (!ce) { - /* Reload bucket pointer, the hash table may have been reallocated */ - zv = zend_hash_find(EG(class_table), Z_STR_P(lcname)); - zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(rtd_key)); - return FAILURE; - } - - return SUCCESS; + return zend_bind_class_in_slot(zv, lcname, lc_parent_name) ? SUCCESS : FAILURE; } /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 9da04beafa1..05874babffb 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -797,6 +797,8 @@ bool zend_handle_encoding_declaration(zend_ast *ast); /* parser-driven code generators */ void zend_do_free(znode *op1); +ZEND_API zend_class_entry *zend_bind_class_in_slot( + zval *class_table_slot, zval *lcname, zend_string *lc_parent_name); ZEND_API zend_result do_bind_function(zend_function *func, zval *lcname); ZEND_API zend_result do_bind_class(zval *lcname, zend_string *lc_parent_name); ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 696d6959e99..e820aef46cf 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7582,27 +7582,16 @@ ZEND_VM_HANDLER(144, ZEND_DECLARE_CLASS, CONST, ANY) ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST) { USE_OPLINE - zval *lcname, *zv; - zend_class_entry *ce; - ce = CACHED_PTR(opline->extended_value); + zend_class_entry *ce = CACHED_PTR(opline->extended_value); if (ce == NULL) { - lcname = RT_CONSTANT(opline, opline->op1); - zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1)); + zval *lcname = RT_CONSTANT(opline, opline->op1); + zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1)); if (zv) { SAVE_OPLINE(); - 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 { - ce = zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(lcname)); - if (!ce) { - /* Reload bucket pointer, the hash table may have been reallocated */ - zv = zend_hash_find(EG(class_table), Z_STR_P(lcname)); - zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1)); - HANDLE_EXCEPTION(); - } + ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2))); + if (!ce) { + HANDLE_EXCEPTION(); } } CACHE_PTR(opline->extended_value, ce); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cee8248567c..92acc5e9b32 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -7355,27 +7355,16 @@ array_key_exists_array: static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *lcname, *zv; - zend_class_entry *ce; - ce = CACHED_PTR(opline->extended_value); + zend_class_entry *ce = CACHED_PTR(opline->extended_value); if (ce == NULL) { - lcname = RT_CONSTANT(opline, opline->op1); - zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1)); + zval *lcname = RT_CONSTANT(opline, opline->op1); + zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1)); if (zv) { SAVE_OPLINE(); - 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 { - ce = zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(lcname)); - if (!ce) { - /* Reload bucket pointer, the hash table may have been reallocated */ - zv = zend_hash_find(EG(class_table), Z_STR_P(lcname)); - zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1)); - HANDLE_EXCEPTION(); - } + ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2))); + if (!ce) { + HANDLE_EXCEPTION(); } } CACHE_PTR(opline->extended_value, ce);