Skip to content

Commit 39b66ba

Browse files
authored
Use zend_hash_find_ptr_lc() for case-insensitive name lookups (php#22565)
A number of call sites lowercased a class/function/method name into a temporary string solely to use it as a lookup key in the class table, function table, module registry, etc., then released it. Replace those with zend_hash_find_ptr_lc() / zend_hash_str_find_ptr_lc(), which lowercase into a stack buffer (for short names), perform the lookup, and free the temporary internally. This removes the manual tolower + release boilerplate at 17 sites and avoids a heap allocation for the common short-name case. No behavior change.
1 parent fc7054a commit 39b66ba

10 files changed

Lines changed: 17 additions & 65 deletions

File tree

Zend/Optimizer/zend_optimizer.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,7 @@ zend_result zend_optimizer_eval_special_func_call(
104104
zval *result, const zend_string *name, zend_string *arg) {
105105
if (zend_string_equals_literal(name, "function_exists") ||
106106
zend_string_equals_literal(name, "is_callable")) {
107-
zend_string *lc_name = zend_string_tolower(arg);
108-
const zend_internal_function *func = zend_hash_find_ptr(EG(function_table), lc_name);
109-
zend_string_release_ex(lc_name, 0);
107+
const zend_internal_function *func = zend_hash_find_ptr_lc(EG(function_table), arg);
110108

111109
if (func && func->type == ZEND_INTERNAL_FUNCTION
112110
&& func->module->type == MODULE_PERSISTENT
@@ -120,9 +118,7 @@ zend_result zend_optimizer_eval_special_func_call(
120118
return FAILURE;
121119
}
122120
if (zend_string_equals_literal(name, "extension_loaded")) {
123-
zend_string *lc_name = zend_string_tolower(arg);
124-
zend_module_entry *m = zend_hash_find_ptr(&module_registry, lc_name);
125-
zend_string_release_ex(lc_name, 0);
121+
zend_module_entry *m = zend_hash_find_ptr_lc(&module_registry, arg);
126122

127123
if (!m) {
128124
if (PG(enable_dl)) {

Zend/zend_builtin_functions.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,6 @@ ZEND_FUNCTION(method_exists)
953953
{
954954
zval *klass;
955955
zend_string *method_name;
956-
zend_string *lcname;
957956
zend_class_entry *ce;
958957
zend_function *func;
959958

@@ -974,9 +973,7 @@ ZEND_FUNCTION(method_exists)
974973
RETURN_THROWS();
975974
}
976975

977-
lcname = zend_string_tolower(method_name);
978-
func = zend_hash_find_ptr(&ce->function_table, lcname);
979-
zend_string_release_ex(lcname, 0);
976+
func = zend_hash_find_ptr_lc(&ce->function_table, method_name);
980977

981978
if (func) {
982979
/* Exclude shadow properties when checking a method on a specific class. Include
@@ -2219,7 +2216,6 @@ ZEND_FUNCTION(extension_loaded)
22192216
ZEND_FUNCTION(get_extension_funcs)
22202217
{
22212218
zend_string *extension_name;
2222-
zend_string *lcname;
22232219
bool array;
22242220
zend_module_entry *module;
22252221
zend_function *zif;
@@ -2228,9 +2224,7 @@ ZEND_FUNCTION(get_extension_funcs)
22282224
RETURN_THROWS();
22292225
}
22302226
if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
2231-
lcname = zend_string_tolower(extension_name);
2232-
module = zend_hash_find_ptr(&module_registry, lcname);
2233-
zend_string_release_ex(lcname, 0);
2227+
module = zend_hash_find_ptr_lc(&module_registry, extension_name);
22342228
} else {
22352229
module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
22362230
}

Zend/zend_inheritance.c

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,7 @@ static zend_class_entry *lookup_class_ex(
264264
bool in_preload = CG(compiler_options) & ZEND_COMPILE_PRELOAD;
265265

266266
if (UNEXPECTED(!EG(active) && !in_preload)) {
267-
zend_string *lc_name = zend_string_tolower(name);
268-
269-
ce = zend_hash_find_ptr(CG(class_table), lc_name);
270-
271-
zend_string_release(lc_name);
267+
ce = zend_hash_find_ptr_lc(CG(class_table), name);
272268

273269
if (register_unresolved && !ce) {
274270
zend_error_noreturn(
@@ -2530,7 +2526,6 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
25302526
size_t i, j = 0;
25312527
zend_trait_precedence *cur_precedence;
25322528
zend_trait_method_reference *cur_method_ref;
2533-
zend_string *lc_trait_name;
25342529
zend_string *lcname;
25352530
HashTable **exclude_tables = NULL;
25362531
zend_class_entry **aliases = NULL;
@@ -2545,9 +2540,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
25452540
while ((cur_precedence = precedences[i])) {
25462541
/** Resolve classes for all precedence operations. */
25472542
cur_method_ref = &cur_precedence->trait_method;
2548-
lc_trait_name = zend_string_tolower(cur_method_ref->class_name);
2549-
trait = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2550-
zend_string_release_ex(lc_trait_name, 0);
2543+
trait = zend_hash_find_ptr_lc(EG(class_table), cur_method_ref->class_name);
25512544
if (!trait || !(trait->ce_flags & ZEND_ACC_LINKED)) {
25522545
zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
25532546
}
@@ -2574,9 +2567,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
25742567
zend_class_entry *exclude_ce;
25752568
uint32_t trait_num;
25762569

2577-
lc_trait_name = zend_string_tolower(class_name);
2578-
exclude_ce = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2579-
zend_string_release_ex(lc_trait_name, 0);
2570+
exclude_ce = zend_hash_find_ptr_lc(EG(class_table), class_name);
25802571
if (!exclude_ce || !(exclude_ce->ce_flags & ZEND_ACC_LINKED)) {
25812572
zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(class_name));
25822573
}
@@ -2619,9 +2610,7 @@ static void zend_traits_init_trait_structures(zend_class_entry *ce, zend_class_e
26192610
lcname = zend_string_tolower(cur_method_ref->method_name);
26202611
if (cur_method_ref->class_name) {
26212612
/* For all aliases with an explicit class name, resolve the class now. */
2622-
lc_trait_name = zend_string_tolower(cur_method_ref->class_name);
2623-
trait = zend_hash_find_ptr(EG(class_table), lc_trait_name);
2624-
zend_string_release_ex(lc_trait_name, 0);
2613+
trait = zend_hash_find_ptr_lc(EG(class_table), cur_method_ref->class_name);
26252614
if (!trait || !(trait->ce_flags & ZEND_ACC_LINKED)) {
26262615
zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", ZSTR_VAL(cur_method_ref->class_name));
26272616
}

ext/hash/hash.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,7 @@ static struct mhash_bc_entry mhash_to_hash[MHASH_NUM_ALGOS] = {
102102

103103
PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(zend_string *algo) /* {{{ */
104104
{
105-
zend_string *lower = zend_string_tolower(algo);
106-
const php_hash_ops *ops = zend_hash_find_ptr(&php_hash_hashtable, lower);
107-
zend_string_release(lower);
105+
const php_hash_ops *ops = zend_hash_find_ptr_lc(&php_hash_hashtable, algo);
108106

109107
return ops;
110108
}

ext/opcache/ZendAccelerator.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3847,9 +3847,7 @@ static zend_result preload_resolve_deps(preload_error *error, const zend_class_e
38473847
memset(error, 0, sizeof(preload_error));
38483848

38493849
if (ce->parent_name) {
3850-
zend_string *key = zend_string_tolower(ce->parent_name);
3851-
const zend_class_entry *parent = zend_hash_find_ptr(EG(class_table), key);
3852-
zend_string_release(key);
3850+
const zend_class_entry *parent = zend_hash_find_ptr_lc(EG(class_table), ce->parent_name);
38533851
if (!parent) {
38543852
error->kind = "Unknown parent ";
38553853
error->name = ZSTR_VAL(ce->parent_name);

ext/pdo/pdo_dbh.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,6 @@ static zend_function *dbh_method_get(zend_object **object, zend_string *method_n
14841484
{
14851485
zend_function *fbc = NULL;
14861486
pdo_dbh_object_t *dbh_obj = php_pdo_dbh_fetch_object(*object);
1487-
zend_string *lc_method_name;
14881487

14891488
if ((fbc = zend_std_get_method(object, method_name, key)) == NULL) {
14901489
/* not a pre-defined method, nor a user-defined method; check
@@ -1497,9 +1496,7 @@ static zend_function *dbh_method_get(zend_object **object, zend_string *method_n
14971496
}
14981497
}
14991498

1500-
lc_method_name = zend_string_tolower(method_name);
1501-
fbc = zend_hash_find_ptr(dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH], lc_method_name);
1502-
zend_string_release_ex(lc_method_name, 0);
1499+
fbc = zend_hash_find_ptr_lc(dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH], method_name);
15031500
}
15041501

15051502
out:

ext/reflection/php_reflection.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,6 @@ static void _function_string(smart_str *str, const zend_function *fptr, const ze
859859
{
860860
smart_str param_indent = {0};
861861
zend_function *overwrites;
862-
zend_string *lc_name;
863862

864863
/* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
865864
* What's "wrong" is that any whitespace before the doc comment start is
@@ -885,13 +884,11 @@ static void _function_string(smart_str *str, const zend_function *fptr, const ze
885884
if (fptr->common.scope != scope) {
886885
smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
887886
} else if (fptr->common.scope->parent) {
888-
lc_name = zend_string_tolower(fptr->common.function_name);
889-
if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
887+
if ((overwrites = zend_hash_find_ptr_lc(&fptr->common.scope->parent->function_table, fptr->common.function_name)) != NULL) {
890888
if (fptr->common.scope != overwrites->common.scope && !(overwrites->common.fn_flags & ZEND_ACC_PRIVATE)) {
891889
smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
892890
}
893891
}
894-
zend_string_release_ex(lc_name, 0);
895892
}
896893
}
897894
if (fptr->common.prototype && fptr->common.prototype->common.scope) {

sapi/cli/php_cli.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,10 +1093,9 @@ static int do_cli(int argc, char **argv) /* {{{ */
10931093
case PHP_CLI_MODE_REFLECTION_EXT_INFO:
10941094
{
10951095
size_t len = strlen(reflection_what);
1096-
char *lcname = zend_str_tolower_dup(reflection_what, len);
10971096
zend_module_entry *module;
10981097

1099-
if ((module = zend_hash_str_find_ptr(&module_registry, lcname, len)) == NULL) {
1098+
if ((module = zend_hash_str_find_ptr_lc(&module_registry, reflection_what, len)) == NULL) {
11001099
if (!strcmp(reflection_what, "main")) {
11011100
display_ini_entries(NULL);
11021101
} else {
@@ -1107,7 +1106,6 @@ static int do_cli(int argc, char **argv) /* {{{ */
11071106
php_info_print_module(module);
11081107
}
11091108

1110-
efree(lcname);
11111109
break;
11121110
}
11131111

sapi/phpdbg/phpdbg_bp.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -966,13 +966,7 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *f
966966
}
967967

968968
if (ops->function_name) {
969-
phpdbg_breakbase_t *brake;
970-
zend_string *fname = zend_string_tolower(ops->function_name);
971-
972-
brake = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname);
973-
974-
zend_string_release(fname);
975-
return brake;
969+
return zend_hash_find_ptr_lc(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], ops->function_name);
976970
} else {
977971
return zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], ZEND_STRL("main"));
978972
}
@@ -982,17 +976,11 @@ static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array *o
982976
{
983977
HashTable *class_table;
984978
phpdbg_breakbase_t *brake = NULL;
985-
zend_string *class_lcname = zend_string_tolower(ops->scope->name);
986-
987-
if ((class_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname))) {
988-
zend_string *lcname = zend_string_tolower(ops->function_name);
989-
990-
brake = zend_hash_find_ptr(class_table, lcname);
991979

992-
zend_string_release(lcname);
980+
if ((class_table = zend_hash_find_ptr_lc(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], ops->scope->name))) {
981+
brake = zend_hash_find_ptr_lc(class_table, ops->function_name);
993982
}
994983

995-
zend_string_release(class_lcname);
996984
return brake;
997985
} /* }}} */
998986

sapi/phpdbg/phpdbg_list.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,12 @@ PHPDBG_LIST(method) /* {{{ */
8888

8989
if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce) == SUCCESS) {
9090
zend_function *function;
91-
char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name));
9291

93-
if ((function = zend_hash_str_find_ptr(&ce->function_table, lcname, strlen(lcname)))) {
92+
if ((function = zend_hash_str_find_ptr_lc(&ce->function_table, param->method.name, strlen(param->method.name)))) {
9493
phpdbg_list_function(function);
9594
} else {
9695
phpdbg_error("Could not find %s::%s", param->method.class, param->method.name);
9796
}
98-
99-
efree(lcname);
10097
} else {
10198
phpdbg_error("Could not find the class %s", param->method.class);
10299
}

0 commit comments

Comments
 (0)