From: Dmitry Stogov Date: Tue, 11 Sep 2007 11:23:12 +0000 (+0000) Subject: - in case of ambiguity class name in namespace call __autoload() only after X-Git-Tag: RELEASE_2_0_0a1~1841 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=618644c201584211fc170831c1dcf2c6818e60d2;p=php - in case of ambiguity class name in namespace call __autoload() only after checking for both (class from current namespace and internal class) - improved class fetching performance - fixed wrong (lowercase) name passed to __autoload() from call_user_func() --- diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index de76ec3658..85bbc5e728 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -333,7 +333,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z if ((UG(unicode) && (colon.u = u_memrchr(name.u, ':', name_len)) && colon.u > name.u && *(colon.u-1) == ':') || (!UG(unicode) && (colon.s = zend_memrchr(name.s, ':', name_len))&& colon.s > name.s && *(colon.s-1) == ':')) { /* compound constant name */ - zend_class_entry **ce = NULL; + zend_class_entry *ce = NULL; int class_name_len = UG(unicode)?colon.u-name.u-1:colon.s-name.s-1; int const_name_len = name_len - class_name_len - 2; zstr constant_name, class_name; @@ -366,7 +366,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z if (lcname_len == sizeof("self")-1 && ZEND_U_EQUAL(type, lcname, lcname_len, "self", sizeof("self")-1)) { if (scope) { - ce = &scope; + ce = scope; } else { zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); retval = 0; @@ -379,7 +379,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z } else if (!scope->parent) { zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); } else { - ce = &scope->parent; + ce = scope->parent; } efree(lcname.v); } else { @@ -427,31 +427,11 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z efree(lcname.v); /* Check for class */ - if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS && - (flags & ZEND_FETCH_CLASS_RT_NS_CHECK) != 0) { - retval = 0; - if ((UG(unicode) && (colon.u = u_memrchr(class_name.u, ':', class_name_len)) && colon.u > class_name.u && *(colon.u-1) == ':') || - (!UG(unicode) && (colon.s = zend_memrchr(class_name.s, ':', class_name_len))&& colon.s > class_name.s && *(colon.s-1) == ':')) { - - if (UG(unicode)) { - colon.u++; - lcname_len = class_name_len - (colon.u - class_name.u); - } else { - colon.s++; - lcname_len = class_name_len - (colon.s - class_name.s); - } - lcname = zend_u_str_case_fold(type, colon, lcname_len, 0, &lcname_len); - if (zend_u_hash_find(CG(class_table), type, lcname, lcname_len+1, (void**)&ce) == SUCCESS && - (*ce)->type == ZEND_INTERNAL_CLASS) { - retval = 1; - } - efree(lcname.v); - } - } + ce = zend_u_fetch_class(type, class_name, class_name_len, flags TSRMLS_CC); } if (retval && ce) { - if (zend_u_hash_find(&((*ce)->constants_table), type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) { + if (zend_u_hash_find(&ce->constants_table, type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) { retval = 0; } } else { @@ -470,7 +450,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z efree(class_name.v); if (retval) { - zval_update_constant_ex(ret_constant, (void*)1, *ce TSRMLS_CC); + zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC); *result = **ret_constant; zval_copy_ctor(result); } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index a214475e90..71b25fb5a7 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -76,9 +76,9 @@ static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LI } } ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC); -ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC); +ZEND_API int zend_lookup_class_ex(char *name, int name_length, char *autoload_name, zend_class_entry ***ce TSRMLS_DC); ZEND_API int zend_u_lookup_class(zend_uchar type, zstr name, int name_length, zend_class_entry ***ce TSRMLS_DC); -ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, int use_autoload, int do_normalize, zend_class_entry ***ce TSRMLS_DC); +ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, zstr autoload_name, int do_normalize, zend_class_entry ***ce TSRMLS_DC); ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC); ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC); ZEND_API int zend_u_eval_string(zend_uchar type, zstr str, zval *retval_ptr, char *string_name TSRMLS_DC); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index e80e5ba427..76c31ce7d1 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -485,7 +485,6 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg; zval const_value; zstr colon; - int len; if (IS_CONSTANT_VISITED(p)) { zend_error(E_ERROR, "Cannot declare self-referencing constant '%v'", Z_UNIVAL_P(p)); @@ -853,7 +852,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } else if (calling_scope && clen == sizeof("parent") - 1 && ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "parent", sizeof("parent")-1)) { ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL; - } else if (zend_u_lookup_class_ex(Z_TYPE_P(fci->function_name), lcname, clen, 1, 0, &pce TSRMLS_CC) == SUCCESS) { + } else if (zend_u_lookup_class_ex(Z_TYPE_P(fci->function_name), lcname, clen, Z_UNIVAL_P(fci->function_name), 0, &pce TSRMLS_CC) == SUCCESS) { ce_child = *pce; } efree(lcname.v); @@ -1126,7 +1125,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } /* }}} */ -ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, int use_autoload, int do_normalize, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ +ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, zstr autoload_name, int do_normalize, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ { zval **args[1]; zval autoload_function; @@ -1174,7 +1173,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, /* The compiler is not-reentrant. Make sure we __autoload() only during run-time * (doesn't impact fuctionality of __autoload() */ - if (!use_autoload || zend_is_compiling(TSRMLS_C)) { + if (!autoload_name.v || zend_is_compiling(TSRMLS_C)) { if (do_normalize) { efree(lc_free.v); } @@ -1197,7 +1196,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, ALLOC_ZVAL(class_name_ptr); INIT_PZVAL(class_name_ptr); - ZVAL_ZSTRL(class_name_ptr, type, name, name_length, 1); + ZVAL_ZSTR(class_name_ptr, type, autoload_name, 1); args[0] = &class_name_ptr; @@ -1261,13 +1260,13 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, ZEND_API int zend_u_lookup_class(zend_uchar type, zstr name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ { - return zend_u_lookup_class_ex(type, name, name_length, 1, 1, ce TSRMLS_CC); + return zend_u_lookup_class_ex(type, name, name_length, name, 1, ce TSRMLS_CC); } /* }}} */ -ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ +ZEND_API int zend_lookup_class_ex(char *name, int name_length, char *autoload_name, zend_class_entry ***ce TSRMLS_DC) /* {{{ */ { - return zend_u_lookup_class_ex(IS_STRING, ZSTR(name), name_length, use_autoload, 1, ce TSRMLS_CC); + return zend_u_lookup_class_ex(IS_STRING, ZSTR(name), name_length, ZSTR(autoload_name), 1, ce TSRMLS_CC); } /* }}} */ @@ -1683,12 +1682,12 @@ check_fetch_type: case ZEND_FETCH_CLASS_AUTO: { if (do_normalize) { lcname = zend_u_str_case_fold(type, class_name, class_name_len, 1, &class_name_len); + do_normalize = 0; /* we've normalized it already, don't do it twice */ } fetch_type = zend_get_class_fetch_type(type, lcname, class_name_len); if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { - if (do_normalize) { + if (lcname.v != class_name.v) { efree(lcname.v); - do_normalize = 0; /* we've normalized it already, don't do it twice */ } goto check_fetch_type; } @@ -1696,38 +1695,46 @@ check_fetch_type: break; } - if (zend_u_lookup_class_ex(type, lcname, class_name_len, use_autoload, do_normalize, &pce TSRMLS_CC)==FAILURE) { + if (do_normalize) { + lcname = zend_u_str_case_fold(type, class_name, class_name_len, 1, &class_name_len); + } + + if (zend_u_lookup_class_ex(type, lcname, class_name_len, ((!rt_ns_check && use_autoload) ? class_name : NULL_ZSTR), 0, &pce TSRMLS_CC)==FAILURE) { if (rt_ns_check) { /* Check if we have internal class with the same name */ - zstr php_name; + zstr php_name = NULL_ZSTR; + uint php_name_len; if (type == IS_UNICODE) { php_name.u = u_memrchr(lcname.u, ':', class_name_len); if (php_name.u) { php_name.u++; - if (zend_u_lookup_class_ex(type, php_name, class_name_len-(php_name.u-lcname.u), 0, do_normalize, &pce TSRMLS_CC)==SUCCESS && - (*pce)->type == ZEND_INTERNAL_CLASS) { - if (lcname.v != class_name.v) { - efree(lcname.v); - } - return *pce; - } + php_name_len = class_name_len-(php_name.u-lcname.u); } } else { php_name.s = zend_memrchr(lcname.s, ':', class_name_len); if (php_name.s) { php_name.s++; - if (zend_u_lookup_class_ex(type, php_name, class_name_len-(php_name.s-lcname.s), 0, do_normalize, &pce TSRMLS_CC)==SUCCESS && - (*pce)->type == ZEND_INTERNAL_CLASS) { - if (lcname.v != class_name.v) { - efree(lcname.v); - } - return *pce; - } + php_name_len = class_name_len-(php_name.s-lcname.s); } } + if (php_name.v && + zend_u_hash_find(EG(class_table), type, php_name, php_name_len+1, (void **) &pce) == SUCCESS && + (*pce)->type == ZEND_INTERNAL_CLASS) { + if (lcname.v != class_name.v) { + efree(lcname.v); + } + return *pce; + } } if (use_autoload) { + if (rt_ns_check && + zend_u_lookup_class_ex(type, lcname, class_name_len, class_name, 0, &pce TSRMLS_CC)==SUCCESS) { + if (lcname.v != class_name.v) { + efree(lcname.v); + } + return *pce; + } if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { zend_error(E_ERROR, "Interface '%R' not found", type, class_name); } else { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index cf8486bd9a..043e9983ea 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2705,8 +2705,6 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY) ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED|CONST, CONST) { zend_op *opline = EX(opline); - zend_class_entry *ce = NULL; - zval **value; if (OP1_TYPE == IS_UNUSED) { if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { @@ -2717,50 +2715,58 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED|CONST, CONST) zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } else if (OP1_TYPE == IS_CONST) { - zend_op *op_data = opline + 1; - zend_constant *c; + } else { + zend_class_entry *ce; + zval **value; + + if (OP1_TYPE == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - ZEND_VM_INC_OPCODE(); + ZEND_VM_INC_OPCODE(); - /* try a constant in namespace */ - if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { - EX_T(opline->result.u.var).tmp_var = c->value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); - EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_NEXT_OPCODE(); + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; } - /* no constant found. try a constant in class */ - ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); - if (!ce) { + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || + Z_TYPE_PP(value) == IS_CONSTANT) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); } - } else { - ce = EX_T(opline->op1.u.var).class_entry; - } - - if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zend_class_entry *old_scope = EG(scope); - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 41d6275748..1756076a38 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2656,8 +2656,6 @@ static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_class_entry *ce = NULL; - zval **value; if (IS_CONST == IS_UNUSED) { if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { @@ -2668,50 +2666,58 @@ static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } else if (IS_CONST == IS_CONST) { - zend_op *op_data = opline + 1; - zend_constant *c; + } else { + zend_class_entry *ce; + zval **value; - ZEND_VM_INC_OPCODE(); + if (IS_CONST == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - /* try a constant in namespace */ - if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { - EX_T(opline->result.u.var).tmp_var = c->value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); - EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_NEXT_OPCODE(); + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; } - /* no constant found. try a constant in class */ - ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); - if (!ce) { + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || + Z_TYPE_PP(value) == IS_CONSTANT) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); } - } else { - ce = EX_T(opline->op1.u.var).class_entry; - } - - if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zend_class_entry *old_scope = EG(scope); - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_NEXT_OPCODE(); } static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -10123,8 +10129,6 @@ static int ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) static int ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_class_entry *ce = NULL; - zval **value; if (IS_VAR == IS_UNUSED) { if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { @@ -10135,50 +10139,58 @@ static int ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR == IS_CONST) { - zend_op *op_data = opline + 1; - zend_constant *c; + } else { + zend_class_entry *ce; + zval **value; - ZEND_VM_INC_OPCODE(); + if (IS_VAR == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - /* try a constant in namespace */ - if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { - EX_T(opline->result.u.var).tmp_var = c->value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); - EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_NEXT_OPCODE(); + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; } - /* no constant found. try a constant in class */ - ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); - if (!ce) { + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || + Z_TYPE_PP(value) == IS_CONSTANT) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); } - } else { - ce = EX_T(opline->op1.u.var).class_entry; - } - if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zend_class_entry *old_scope = EG(scope); - - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_NEXT_OPCODE(); } static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -16853,8 +16865,6 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_op *opline = EX(opline); - zend_class_entry *ce = NULL; - zval **value; if (IS_UNUSED == IS_UNUSED) { if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { @@ -16865,50 +16875,58 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); } ZEND_VM_NEXT_OPCODE(); - } else if (IS_UNUSED == IS_CONST) { - zend_op *op_data = opline + 1; - zend_constant *c; + } else { + zend_class_entry *ce; + zval **value; - ZEND_VM_INC_OPCODE(); + if (IS_UNUSED == IS_CONST) { + zend_op *op_data = opline + 1; + zend_constant *c; - /* try a constant in namespace */ - if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { - EX_T(opline->result.u.var).tmp_var = c->value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - ZEND_VM_NEXT_OPCODE(); - } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { - if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), - Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); - EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + ZEND_VM_INC_OPCODE(); + + /* try a constant in namespace */ + if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) { + EX_T(opline->result.u.var).tmp_var = c->value; zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + ZEND_VM_NEXT_OPCODE(); + } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) { + if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'", + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), + Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } + ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_NEXT_OPCODE(); + + /* no constant found. try a constant in class */ + ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); + if (!ce) { + zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + } + } else { + ce = EX_T(opline->op1.u.var).class_entry; } - /* no constant found. try a constant in class */ - ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC); - if (!ce) { + if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { + if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY || + Z_TYPE_PP(value) == IS_CONSTANT) { + zend_class_entry *old_scope = EG(scope); + + EG(scope) = ce; + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EG(scope) = old_scope; + } + EX_T(opline->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); + } else { zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); } - } else { - ce = EX_T(opline->op1.u.var).class_entry; - } - - if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) { - zend_class_entry *old_scope = EG(scope); - EG(scope) = ce; - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EG(scope) = old_scope; - EX_T(opline->result.u.var).tmp_var = **value; - zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var); - } else { - zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant)); + ZEND_VM_NEXT_OPCODE(); } - - ZEND_VM_NEXT_OPCODE(); } static int ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)