]> granicus.if.org Git - php/commitdiff
Avoid string comparisons for magic methods (all magic methods start with "__")
authorDmitry Stogov <dmitry@zend.com>
Mon, 2 Jul 2018 14:03:02 +0000 (17:03 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 2 Jul 2018 14:03:02 +0000 (17:03 +0300)
Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_inheritance.c

index 7e440eea1daaba9e8b2a30095c60f16c5e1290e3..20b2d65b8d775117759a84fee91d36cc51f7a182 100644 (file)
@@ -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)) {
index 310fac9cc973eb898e6fffbec2f80f12b4f12490..46fb08986285a8c70e8729dbcb4cb3a67038e874 100644 (file)
@@ -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)) {
index be605a49de6c22c07c87ecfc31c9fff8eaf1e2b6..b66464c37542a553972c17156f4df9221833cb75 100644 (file)
@@ -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);
        }
 }
 /* }}} */