From 06678646310d6bf0e11ce79645c274ed3603a870 Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Tue, 18 Jul 2006 17:52:45 +0000 Subject: [PATCH] Callable checks and class fetching and lookup should support identifer normalization now. (Marcus, Andrei) --- Zend/zend_API.c | 20 ++-------- Zend/zend_builtin_functions.c | 2 +- Zend/zend_compile.h | 4 +- Zend/zend_execute.c | 2 +- Zend/zend_execute.h | 2 +- Zend/zend_execute_API.c | 65 +++++++++++++++++++++++++-------- Zend/zend_language_scanner.l | 2 +- Zend/zend_operators.c | 11 +++++- Zend/zend_unicode.c | 8 ++-- ext/reflection/php_reflection.c | 2 +- 10 files changed, 74 insertions(+), 44 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 065e66653e..2dad1fda49 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2578,10 +2578,9 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, zend_class_entry *ce_org, zval *callable, zend_class_entry **ce_ptr, zend_function **fptr_ptr TSRMLS_DC) { int retval; - zstr lcname, lmname, mname, colon; + zstr lmname, mname, colon; unsigned int clen, mlen; zend_function *fptr; - zend_class_entry **pce; HashTable *ftable; *ce_ptr = NULL; @@ -2601,18 +2600,7 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze } } if (colon.v != NULL) { - lcname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, 0, &clen); - /* caution: lcname is not '\0' terminated */ - if (clen == sizeof("self") - 1 && - ZEND_U_EQUAL(Z_TYPE_P(callable), lcname, clen, "self", sizeof("self")-1)) { - *ce_ptr = EG(scope); - } else if (clen == sizeof("parent") - 1 && - ZEND_U_EQUAL(Z_TYPE_P(callable), lcname, clen, "parent", sizeof("parent")-1)) { - *ce_ptr = EG(scope) ? EG(scope)->parent : NULL; - } else if (zend_u_lookup_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, &pce TSRMLS_CC) == SUCCESS) { - *ce_ptr = *pce; - } - efree(lcname.v); + *ce_ptr = zend_u_fetch_class(Z_TYPE_P(callable), Z_UNIVAL_P(callable), clen, ZEND_FETCH_CLASS_AUTO TSRMLS_CC); if (!*ce_ptr) { return 0; } @@ -2620,9 +2608,9 @@ static int zend_is_callable_check_func(int check_flags, zval ***zobj_ptr_ptr, ze if (ce_org && !instanceof_function(ce_org, *ce_ptr TSRMLS_CC)) { return 0; } - lmname = zend_u_str_case_fold(Z_TYPE_P(callable), mname, mlen, 0, &mlen); + lmname = zend_u_str_case_fold(Z_TYPE_P(callable), mname, mlen, 1, &mlen); } else { - lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 0, &mlen); + lmname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &mlen); if (ce_org) { ftable = &ce_org->function_table; *ce_ptr = ce_org; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 4b728e6860..727310fceb 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -702,7 +702,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) convert_to_text_ex(class_name); - if (zend_u_lookup_class_ex(Z_TYPE_PP(class_name), Z_UNIVAL_PP(class_name), Z_UNILEN_PP(class_name), (instance_ce != NULL) ? 1 : 0, &ce TSRMLS_CC) == FAILURE) { + if (zend_u_lookup_class_ex(Z_TYPE_PP(class_name), Z_UNIVAL_PP(class_name), Z_UNILEN_PP(class_name), (instance_ce != NULL) ? 1 : 0, 1, &ce TSRMLS_CC) == FAILURE) { retval = 0; } else { if (only_subclass) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 28452d8319..606ef14107 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -615,7 +615,9 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_CLASS_GLOBAL 4 #define ZEND_FETCH_CLASS_AUTO 5 #define ZEND_FETCH_CLASS_INTERFACE 6 -#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80 +#define ZEND_FETCH_CLASS_FLAGS 0xF0 +#define ZEND_FETCH_CLASS_NO_NORMALIZE 0x10 +#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80 /* variable parsing type (compile-time) */ #define ZEND_PARSED_MEMBER (1<<0) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 43c23eceed..ecd788f9b9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -943,7 +943,7 @@ fetch_string_dim: UChar *norm; int norm_len; - if (!zend_normalize_identifier(&norm, &norm_len, offset_key.u, offset_key_length, 0)) { + if (zend_normalize_identifier(&norm, &norm_len, offset_key.u, offset_key_length, 0) == FAILURE) { zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key); } else if (norm != offset_key.u) { offset_key.u = norm; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 09432f77b4..79e62376fe 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -71,7 +71,7 @@ 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_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, 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_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 3563286b26..89640e9bef 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -785,7 +785,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } if (Z_TYPE_P(fci->function_name) == IS_UNICODE) { - if ((colon.u = u_strstr(Z_USTRVAL_P(fci->function_name), (UChar*)":\0:\0")) != NULL) { + if ((colon.u = u_strstr(Z_USTRVAL_P(fci->function_name), u_doublecolon)) != NULL) { fname_len = u_strlen(colon.u+2); clen = Z_USTRLEN_P(fci->function_name) - fname_len - 2; fname.u = colon.u + 2; @@ -800,7 +800,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (colon.v != NULL) { zend_class_entry **pce, *ce_child = NULL; - lcname = zend_u_str_case_fold(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), clen, 0, &clen); + lcname = zend_u_str_case_fold(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), clen, 1, &clen); /* caution: lcname is not '\0' terminated */ if (calling_scope && clen == sizeof("self") - 1 && ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "self", sizeof("self")-1)) { @@ -808,7 +808,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(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), clen, &pce TSRMLS_CC) == SUCCESS) { + } else if (zend_u_lookup_class_ex(Z_TYPE_P(fci->function_name), lcname, clen, 1, 0, &pce TSRMLS_CC) == SUCCESS) { ce_child = *pce; } efree(lcname.v); @@ -1063,7 +1063,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, 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) { zval **args[1]; zval autoload_function; @@ -1081,10 +1081,17 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, return FAILURE; } - lc_name = zend_u_str_case_fold(type, name, name_length, 1, &lc_name_len); + if (do_normalize) { + lc_name = zend_u_str_case_fold(type, name, name_length, 1, &lc_name_len); + } else { + lc_name = name; + lc_name_len = name_length; + } if (zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) ce) == SUCCESS) { - efree(lc_name.v); + if (do_normalize) { + efree(lc_name.v); + } return SUCCESS; } @@ -1092,7 +1099,9 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, * (doesn't impact fuctionality of __autoload() */ if (!use_autoload || zend_is_compiling(TSRMLS_C)) { - efree(lc_name.v); + if (do_normalize) { + efree(lc_name.v); + } return FAILURE; } @@ -1102,7 +1111,9 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, } if (zend_u_hash_add(EG(in_autoload), type, lc_name, lc_name_len+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) { - efree(lc_name.v); + if (do_normalize) { + efree(lc_name.v); + } return FAILURE; } @@ -1144,12 +1155,16 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, if (retval == FAILURE) { EG(exception) = exception; - efree(lc_name.v); + if (do_normalize) { + efree(lc_name.v); + } return FAILURE; } if (EG(exception) && exception) { - efree(lc_name.v); + if (do_normalize) { + efree(lc_name.v); + } zend_error(E_ERROR, "Function %s(%R) threw an exception of type '%v'", ZEND_AUTOLOAD_FUNC_NAME, type, name, Z_OBJCE_P(EG(exception))->name); return FAILURE; } @@ -1161,13 +1176,15 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, } retval = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len + 1, (void **) ce); - efree(lc_name.v); + if (do_normalize) { + efree(lc_name.v); + } return retval; } 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, ce TSRMLS_CC); + return zend_u_lookup_class_ex(type, name, name_length, 1, 1, ce TSRMLS_CC); } ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) @@ -1546,9 +1563,12 @@ void zend_unset_timeout(TSRMLS_D) ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, zstr class_name, uint class_name_len, int fetch_type TSRMLS_DC) { zend_class_entry **pce; - int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) == 0; + int use_autoload = (fetch_type & ZEND_FETCH_CLASS_NO_AUTOLOAD) ? 0 : 1; + int do_normalize = (fetch_type & ZEND_FETCH_CLASS_NO_NORMALIZE) ? 0 : 1; + zstr lcname = class_name; + + fetch_type = fetch_type & ~ZEND_FETCH_CLASS_FLAGS; - fetch_type = fetch_type & ~ZEND_FETCH_CLASS_NO_AUTOLOAD; check_fetch_type: switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: @@ -1565,15 +1585,22 @@ check_fetch_type: } return EG(scope)->parent; case ZEND_FETCH_CLASS_AUTO: { - fetch_type = zend_get_class_fetch_type(type, class_name, class_name_len); + if (do_normalize) { + lcname = zend_u_str_case_fold(type, class_name, class_name_len, 1, &class_name_len); + } + fetch_type = zend_get_class_fetch_type(type, lcname, class_name_len); if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { + if (do_normalize) { + efree(lcname.v); + do_normalize = 0; /* we've normalized it already, don't do it twice */ + } goto check_fetch_type; } } break; } - if (zend_u_lookup_class_ex(type, class_name, class_name_len, use_autoload, &pce TSRMLS_CC)==FAILURE) { + if (zend_u_lookup_class_ex(type, lcname, class_name_len, use_autoload, do_normalize, &pce TSRMLS_CC)==FAILURE) { if (use_autoload) { if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) { zend_error(E_ERROR, "Interface '%R' not found", type, class_name); @@ -1581,8 +1608,14 @@ check_fetch_type: zend_error(E_ERROR, "Class '%R' not found", type, class_name); } } + if (lcname.v != class_name.v) { + efree(lcname.v); + } return NULL; } else { + if (lcname.v != class_name.v) { + efree(lcname.v); + } return *pce; } } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index adebc96ba0..036b5a07ef 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -444,7 +444,7 @@ static inline int zend_check_and_normalize_identifier(zval *zendlval) efree(Z_USTRVAL_P(zendlval)); return 0; } - if (!zend_normalize_identifier(&norm, &norm_len, Z_USTRVAL_P(zendlval), Z_USTRLEN_P(zendlval), 0)) { + if (zend_normalize_identifier(&norm, &norm_len, Z_USTRVAL_P(zendlval), Z_USTRLEN_P(zendlval), 0) == FAILURE) { zend_error(E_COMPILE_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(zendlval)); efree(Z_USTRVAL_P(zendlval)); return 0; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index aaeba61a77..b377a0f62a 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2108,14 +2108,21 @@ ZEND_API zstr zend_u_str_case_fold(zend_uchar type, zstr source, unsigned int le zstr ret; if (type == IS_UNICODE) { - int ret_len; + int ret_len = length; if (normalize) { - zend_normalize_identifier(&ret.u, &ret_len, source.u, length, 1); + if (zend_normalize_identifier(&ret.u, &ret_len, source.u, length, 1) == FAILURE) { + zend_error(E_NOTICE, "Could not normalize identifier"); + ret.u = eustrndup(source.u, length); + } } else { UErrorCode status = U_ZERO_ERROR; zend_case_fold_string(&ret.u, &ret_len, source.u, length, U_FOLD_CASE_DEFAULT, &status); + if (U_FAILURE(status)) { + zend_error(E_NOTICE, "Could not case-fold string"); + ret.u = eustrndup(source.u, length); + } } *new_len = ret_len; diff --git a/Zend/zend_unicode.c b/Zend/zend_unicode.c index 51b6938f25..47d5f7be6b 100644 --- a/Zend/zend_unicode.c +++ b/Zend/zend_unicode.c @@ -736,7 +736,7 @@ ZEND_API int zend_normalize_identifier(UChar **dest, int *dest_len, UChar *ident if (unorm_quickCheck(ident, ident_len, UNORM_NFKC, &status) != UNORM_YES) { zend_normalize_string(&buffer, &buffer_len, ident, ident_len, &status); if (U_FAILURE(status)) { - return 0; + return FAILURE; } ident = buffer; ident_len = buffer_len; @@ -748,7 +748,7 @@ ZEND_API int zend_normalize_identifier(UChar **dest, int *dest_len, UChar *ident efree(ident); } if (U_FAILURE(status)) { - return 0; + return FAILURE; } ident = buffer; ident_len = buffer_len; @@ -759,7 +759,7 @@ ZEND_API int zend_normalize_identifier(UChar **dest, int *dest_len, UChar *ident efree(ident); } if (U_FAILURE(status)) { - return 0; + return FAILURE; } ident = buffer; ident_len = buffer_len; @@ -768,7 +768,7 @@ ZEND_API int zend_normalize_identifier(UChar **dest, int *dest_len, UChar *ident *dest = ident; *dest_len = ident_len; - return 1; + return SUCCESS; } /* }}} */ diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index b12a5646bd..afccde7234 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1972,7 +1972,7 @@ ZEND_METHOD(reflection_parameter, getClass) GET_REFLECTION_OBJECT_PTR(param); if (param->arg_info->class_name.v) { - if (zend_u_lookup_class_ex(UG(unicode)?IS_UNICODE:IS_STRING, param->arg_info->class_name, param->arg_info->class_name_len, 1, &pce TSRMLS_CC) == FAILURE) { + if (zend_u_lookup_class_ex(UG(unicode)?IS_UNICODE:IS_STRING, param->arg_info->class_name, param->arg_info->class_name_len, 1, 1, &pce TSRMLS_CC) == FAILURE) { zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %v does not exist", param->arg_info->class_name); return; -- 2.40.0