diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2018-07-02 17:03:02 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2018-07-02 17:03:02 +0300 |
| commit | 43aca3118ab011b878ec577904eafc18f86f69ae (patch) | |
| tree | 96ea9c20bebffe97ab9dcea311c681845aef6a9b | |
| parent | a63e834b66046d507c8f67de3c9a7251c4e327f4 (diff) | |
| download | php-git-43aca3118ab011b878ec577904eafc18f86f69ae.tar.gz | |
Avoid string comparisons for magic methods (all magic methods start with "__")
| -rw-r--r-- | Zend/zend_API.c | 7 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 8 | ||||
| -rw-r--r-- | Zend/zend_inheritance.c | 26 |
3 files changed, 28 insertions, 13 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 7e440eea1d..20b2d65b8d 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2090,6 +2090,11 @@ ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, char lcname[16]; size_t name_len; + if (ZSTR_VAL(fptr->common.function_name)[0] != '_' + || ZSTR_VAL(fptr->common.function_name)[1] != '_') { + return; + } + /* we don't care if the function name is longer, in fact lowercasing only * the beginning of the name speeds up the check process */ 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 */ if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) { ctor = reg_function; + } else if (ZSTR_VAL(lowercase_name)[0] != '_' || ZSTR_VAL(lowercase_name)[1] != '_') { + reg_function = NULL; } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) { ctor = reg_function; } else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 310fac9cc9..46fb089862 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5772,7 +5772,9 @@ void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_boo } if (in_interface) { - if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { + if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { + /* pass */ + } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) { if (!is_public || is_static) { zend_error(E_WARNING, "The magic method __call() must have " "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 if (!ce->constructor) { ce->constructor = (zend_function *) op_array; } + } else if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') { + if (!is_static) { + op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC; + } } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) { ce->constructor = (zend_function *) op_array; } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) { diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index be605a49de..b66464c375 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1115,7 +1115,20 @@ static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zend_function* fe) /* {{{ */ { - if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) { + if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) { + zend_string *lowercase_name = zend_string_tolower(ce->name); + lowercase_name = zend_new_interned_string(lowercase_name); + if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) { + if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) { + zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name)); + } + ce->constructor = fe; + fe->common.fn_flags |= ZEND_ACC_CTOR; + } + zend_string_release_ex(lowercase_name, 0); + } else if (ZSTR_VAL(mname)[0] != '_' || ZSTR_VAL(mname)[1] != '_') { + /* pass */ + } else if (zend_string_equals_literal(mname, ZEND_CLONE_FUNC_NAME)) { ce->clone = fe; } else if (zend_string_equals_literal(mname, ZEND_CONSTRUCTOR_FUNC_NAME)) { 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 ce->__tostring = fe; } else if (zend_string_equals_literal(mname, ZEND_DEBUGINFO_FUNC_NAME)) { ce->__debugInfo = fe; - } else if (ZSTR_LEN(ce->name) == ZSTR_LEN(mname)) { - zend_string *lowercase_name = zend_string_tolower(ce->name); - lowercase_name = zend_new_interned_string(lowercase_name); - if (!memcmp(ZSTR_VAL(mname), ZSTR_VAL(lowercase_name), ZSTR_LEN(mname))) { - if (ce->constructor && (!ce->parent || ce->constructor != ce->parent->constructor)) { - zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ZSTR_VAL(ce->name)); - } - ce->constructor = fe; - fe->common.fn_flags |= ZEND_ACC_CTOR; - } - zend_string_release_ex(lowercase_name, 0); } } /* }}} */ |
