From 90db6f2cc539d99a1396a337ed0928c3f642255b Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Fri, 24 Apr 2020 15:00:13 -0600 Subject: [PATCH] Add case insensitive find_ptr hash functions - zend_hash_find_ptr_lc(ht, zend_string *key) - zend_hash_str_find_ptr_lc(ht, const char *str, size_t len) Note that zend_hash_str_find_ptr_lc used to exist in zend_compile.c as zend_hash_find_ptr_lc. When exporting this I figured it was best to use the same conventions as the rest of zend_hash.h. --- Zend/zend_compile.c | 36 +++++++++++------------------------- Zend/zend_hash.c | 22 ++++++++++++++++++++++ Zend/zend_hash.h | 8 ++++++++ 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 472a402fe6b..381a180f295 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -272,23 +272,9 @@ static zend_always_inline zend_bool zend_is_confusable_type(const zend_string *n } /* }}} */ -static void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) { - void *result; - zend_string *lcname; - ALLOCA_FLAG(use_heap); - - ZSTR_ALLOCA_ALLOC(lcname, len, use_heap); - zend_str_tolower_copy(ZSTR_VAL(lcname), str, len); - result = zend_hash_find_ptr(ht, lcname); - ZSTR_ALLOCA_FREE(lcname, use_heap); - - return result; -} - static zend_bool zend_is_not_imported(zend_string *name) { /* Assuming "name" is unqualified here. */ - return !FC(imports) - || zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), ZSTR_LEN(name)) == NULL; + return !FC(imports) || zend_hash_find_ptr_lc(FC(imports), name) == NULL; } void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */ @@ -901,7 +887,7 @@ zend_string *zend_resolve_non_class_name( if (case_sensitive) { import_name = zend_hash_find_ptr(current_import_sub, name); } else { - import_name = zend_hash_find_ptr_lc(current_import_sub, ZSTR_VAL(name), ZSTR_LEN(name)); + import_name = zend_hash_find_ptr_lc(current_import_sub, name); } if (import_name) { @@ -918,7 +904,7 @@ zend_string *zend_resolve_non_class_name( if (compound && FC(imports)) { /* If the first part of a qualified name is an alias, substitute it. */ size_t len = compound - ZSTR_VAL(name); - zend_string *import_name = zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); + zend_string *import_name = zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); if (import_name) { return zend_concat_names( @@ -971,7 +957,7 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */ /* If the first part of a qualified name is an alias, substitute it. */ size_t len = compound - ZSTR_VAL(name); zend_string *import_name = - zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); + zend_hash_str_find_ptr_lc(FC(imports), ZSTR_VAL(name), len); if (import_name) { return zend_concat_names( @@ -980,7 +966,7 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */ } else { /* If an unqualified name is an alias, replace it. */ zend_string *import_name - = zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), ZSTR_LEN(name)); + = zend_hash_find_ptr_lc(FC(imports), name); if (import_name) { return zend_string_copy(import_name); @@ -1613,7 +1599,7 @@ static zend_bool zend_verify_ct_const_access(zend_class_constant *c, zend_class_ if (ce->ce_flags & ZEND_ACC_RESOLVED_PARENT) { ce = ce->parent; } else { - ce = zend_hash_find_ptr_lc(CG(class_table), ZSTR_VAL(ce->parent_name), ZSTR_LEN(ce->parent_name)); + ce = zend_hash_find_ptr_lc(CG(class_table), ce->parent_name); if (!ce) { break; } @@ -1633,7 +1619,7 @@ static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, if (class_name_refers_to_active_ce(class_name, fetch_type)) { cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name); } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) { - zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), ZSTR_VAL(class_name), ZSTR_LEN(class_name)); + zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name); if (ce) { cc = zend_hash_find_ptr(&ce->constants_table, name); } else { @@ -6191,8 +6177,8 @@ static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_as lcname = zend_string_tolower(name); if (FC(imports_function)) { - zend_string *import_name = zend_hash_find_ptr_lc( - FC(imports_function), ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name)); + zend_string *import_name = + zend_hash_find_ptr_lc(FC(imports_function), unqualified_name); if (import_name && !zend_string_equals_ci(lcname, import_name)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare function %s " "because the name is already in use", ZSTR_VAL(name)); @@ -6657,8 +6643,8 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) / lcname = zend_string_tolower(name); if (FC(imports)) { - zend_string *import_name = zend_hash_find_ptr_lc( - FC(imports), ZSTR_VAL(unqualified_name), ZSTR_LEN(unqualified_name)); + zend_string *import_name = + zend_hash_find_ptr_lc(FC(imports), unqualified_name); if (import_name && !zend_string_equals_ci(lcname, import_name)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s " "because the name is already in use", ZSTR_VAL(name)); diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 872a2282294..d57c0a69d2e 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -84,6 +84,28 @@ static void _zend_is_inconsistent(const HashTable *ht, const char *file, int lin zend_hash_do_resize(ht); \ } +ZEND_API void *zend_hash_str_find_ptr_lc(const HashTable *ht, const char *str, size_t len) { + void *result; + char *lc_str; + + /* Stack allocate small strings to improve performance */ + ALLOCA_FLAG(use_heap) + + lc_str = zend_str_tolower_copy(do_alloca(len + 1, use_heap), str, len); + result = zend_hash_str_find_ptr(ht, lc_str, len); + free_alloca(lc_str, use_heap); + + return result; +} + +ZEND_API void *zend_hash_find_ptr_lc(const HashTable *ht, zend_string *key) { + void *result; + zend_string *lc_key = zend_string_tolower(key); + result = zend_hash_find_ptr(ht, lc_key); + zend_string_release(lc_key); + return result; +} + static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht); static zend_always_inline uint32_t zend_hash_check_size(uint32_t nSize) diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 289b9a3349d..632658d9387 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -847,6 +847,14 @@ static zend_always_inline void *zend_hash_str_find_ptr(const HashTable *ht, cons } } +/* Will lowercase the str; use only if you don't need the lowercased string for + * anything else. If you have a lowered string, use zend_hash_str_find_ptr. */ +ZEND_API void *zend_hash_str_find_ptr_lc(const HashTable *ht, const char *str, size_t len); + +/* Will lowercase the str; use only if you don't need the lowercased string for + * anything else. If you have a lowered string, use zend_hash_find_ptr. */ +ZEND_API void *zend_hash_find_ptr_lc(const HashTable *ht, zend_string *key); + static zend_always_inline void *zend_hash_index_find_ptr(const HashTable *ht, zend_ulong h) { zval *zv;