Skip to content

Commit 43aca31

Browse files
committed
Avoid string comparisons for magic methods (all magic methods start with "__")
1 parent a63e834 commit 43aca31

File tree

3 files changed

+28
-13
lines changed

3 files changed

+28
-13
lines changed

Zend/zend_API.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,11 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce,
20902090
char lcname[16];
20912091
size_t name_len;
20922092

2093+
if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
2094+
|| ZSTR_VAL(fptr->common.function_name)[1] != '_') {
2095+
return;
2096+
}
2097+
20932098
/* we don't care if the function name is longer, in fact lowercasing only
20942099
* the beginning of the name speeds up the check process */
20952100
name_len = ZSTR_LEN(fptr->common.function_name);
@@ -2333,6 +2338,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
23332338
*/
23342339
if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) {
23352340
ctor = reg_function;
2341+
} else if (ZSTR_VAL(lowercase_name)[0] != '_' || ZSTR_VAL(lowercase_name)[1] != '_') {
2342+
reg_function = NULL;
23362343
} else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
23372344
ctor = reg_function;
23382345
} else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) {

Zend/zend_compile.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5772,7 +5772,9 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo
57725772
}
57735773

57745774
if (in_interface) {
5775-
if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
5775+
if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
5776+
/* pass */
5777+
} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
57765778
if (!is_public || is_static) {
57775779
zend_error(E_WARNING, "The magic method __call() must have "
57785780
"public visibility and cannot be static");
@@ -5823,6 +5825,10 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo
58235825
if (!ce->constructor) {
58245826
ce->constructor = (zend_function *) op_array;
58255827
}
5828+
} else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
5829+
if (!is_static) {
5830+
op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC;
5831+
}
58265832
} else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
58275833
ce->constructor = (zend_function *) op_array;
58285834
} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {

Zend/zend_inheritance.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,20 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_
11151115

11161116
static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe) /* {{{ */
11171117
{
1118-
if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
1118+
if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
1119+
zend_string *lowercase_name = zend_string_tolower(ce->name);
1120+
lowercase_name = zend_new_interned_string(lowercase_name);
1121+
if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) {
1122+
if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
1123+
zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
1124+
}
1125+
ce->constructor = fe;
1126+
fe->common.fn_flags |= ZEND_ACC_CTOR;
1127+
}
1128+
zend_string_release_ex(lowercase_name, 0);
1129+
} else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') {
1130+
/* pass */
1131+
} else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) {
11191132
ce->clone = fe;
11201133
} else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
11211134
if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
@@ -1144,17 +1157,6 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen
11441157
ce->__tostring = fe;
11451158
} else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) {
11461159
ce->__debugInfo = fe;
1147-
} else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) {
1148-
zend_string *lowercase_name = zend_string_tolower(ce->name);
1149-
lowercase_name = zend_new_interned_string(lowercase_name);
1150-
if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) {
1151-
if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) {
1152-
zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name));
1153-
}
1154-
ce->constructor = fe;
1155-
fe->common.fn_flags |= ZEND_ACC_CTOR;
1156-
}
1157-
zend_string_release_ex(lowercase_name, 0);
11581160
}
11591161
}
11601162
/* }}} */

0 commit comments

Comments
 (0)