]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.4'
authorDmitry Stogov <dmitry@zend.com>
Wed, 26 Jun 2019 23:25:57 +0000 (02:25 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 26 Jun 2019 23:25:57 +0000 (02:25 +0300)
* PHP-7.4:
  Avoid double checks on early binding

1  2 
Zend/zend_compile.c
Zend/zend_inheritance.c
Zend/zend_inheritance.h

index c69735ebc19ffb41b287a6392f3446205ecebdb3,fc6dcf5bb7f17843233e2cb11f202bbd66d8a99a..3d32a087f19089e9603ce312d2d64c4c9eed47a3
@@@ -6349,12 -6444,15 +6330,13 @@@ zend_op *zend_compile_class_decl(zend_a
                                        zend_string_release(lcname);
                                        return NULL;
                                }
+                               CG(zend_lineno) = ast->lineno;
                        }
 -              } else {
 -                      if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
 -                              zend_string_release(lcname);
 -                              zend_build_properties_info_table(ce);
 -                              ce->ce_flags |= ZEND_ACC_LINKED;
 -                              return NULL;
 -                      }
 +              } else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
 +                      zend_string_release(lcname);
 +                      zend_build_properties_info_table(ce);
 +                      ce->ce_flags |= ZEND_ACC_LINKED;
 +                      return NULL;
                }
        }
  
index 9e3707ad6d58012475749694665f0246afc5a31e,0877f7a70b4d54770fb0fb8b2754b528b6935f20..f79096edfbcd673fd256d37f9720674ca0db69ce
@@@ -771,7 -812,23 +783,22 @@@ static zend_always_inline inheritance_s
                        ZEND_FN_SCOPE_NAME(child), ZSTR_VAL(child->common.function_name), zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
        }
  
-       perform_delayable_implementation_check(ce, child, parent);
+       if (!checked) {
+               if (check_only) {
+                       zend_string *unresolved_class;
+                       return zend_do_perform_implementation_check(
+                               &unresolved_class, child, parent);
+               }
 -              perform_delayable_implementation_check(
 -                      ce, child, parent, /*always_error*/0);
++              perform_delayable_implementation_check(ce, child, parent);
+       }
+       return INHERITANCE_SUCCESS;
+ }
+ /* }}} */
+ static void do_inheritance_check_on_method(zend_function *child, zend_function *parent, zend_class_entry *ce, zval *child_zv) /* {{{ */
+ {
+       do_inheritance_check_on_method_ex(child, parent, ce, child_zv, 0, 0);
  }
  /* }}} */
  
@@@ -2305,39 -2440,48 +2360,43 @@@ ZEND_API void zend_do_link_class(zend_c
                }
        }
  }
+ /* }}} */
  
  /* Check whether early binding is prevented due to unresolved types in inheritance checks. */
- zend_bool zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) {
+ static inheritance_status zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
+ {
 -      inheritance_status ret = INHERITANCE_SUCCESS;
        zend_string *key;
        zend_function *parent_func;
-       ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) {
-               uint32_t parent_flags = parent_func->common.fn_flags;
-               zval *zv;
-               zend_string *unresolved_class;
  
-               if (parent_flags & ZEND_ACC_PRIVATE) {
-                       continue;
-               } else if (parent_flags & ZEND_ACC_CTOR) {
-                       zend_function *proto = parent_func->common.prototype ?
-                               parent_func->common.prototype : parent_func;
+       ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->function_table, key, parent_func) {
+               zval *zv = zend_hash_find_ex(&ce->function_table, key, 1);
+               if (zv) {
+                       zend_function *child_func = Z_FUNC_P(zv);
+                       inheritance_status status =
+                               do_inheritance_check_on_method_ex(child_func, parent_func, ce, NULL, 1, 0);
  
-                       /* ctors only have a prototype if is abstract (or comes from an interface) */
-                       /* and if that is the case, we want to check inheritance against it */
-                       if (!(proto->common.fn_flags & ZEND_ACC_ABSTRACT)) {
-                               continue;
+                       if (UNEXPECTED(status != INHERITANCE_SUCCESS)) {
 -                              if (EXPECTED(status == INHERITANCE_UNRESOLVED)) {
 -                                      return INHERITANCE_UNRESOLVED;
 -                              }
 -                              ZEND_ASSERT(status == INHERITANCE_ERROR);
 -                              ret = INHERITANCE_ERROR;
++                              return status;
                        }
-                       parent_func = proto;
                }
+       } ZEND_HASH_FOREACH_END();
  
-               zv = zend_hash_find_ex(&ce->function_table, key, 1);
-               if (zv) {
-                       zend_function *child_func = Z_FUNC_P(zv);
-                       inheritance_status status;
 -      return ret;
++      return INHERITANCE_SUCCESS;
+ }
+ /* }}} */
  
-                       status = zend_do_perform_implementation_check(
-                                       &unresolved_class, child_func, parent_func);
+ zend_bool zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding) /* {{{ */
+ {
+       inheritance_status status = zend_can_early_bind(ce, parent_ce);
  
-                       if (UNEXPECTED(status == INHERITANCE_UNRESOLVED)) {
+       if (EXPECTED(status != INHERITANCE_UNRESOLVED)) {
+               if (delayed_early_binding) {
+                       if (UNEXPECTED(zend_hash_set_bucket_key(EG(class_table), (Bucket*)delayed_early_binding, lcname) == NULL)) {
+                               zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
+                               return 0;
+                       }
+               } else {
+                       if (UNEXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) == NULL)) {
                                return 0;
                        }
                }
index d5d624cf20ba45f17a2d69753b4fdbc0333aecac,120a56a1efb0b990a04e3d110ac42e8785d001fd..05352052cc237a446eddc09214ddc96151360837
@@@ -30,8 -33,9 +33,8 @@@ ZEND_API void zend_do_inheritance_ex(ze
  ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name);
  
  void zend_verify_abstract_class(zend_class_entry *ce);
 -void zend_check_deprecated_constructor(const zend_class_entry *ce);
  void zend_build_properties_info_table(zend_class_entry *ce);
- zend_bool zend_can_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce);
+ zend_bool zend_try_early_bind(zend_class_entry *ce, zend_class_entry *parent_ce, zend_string *lcname, zval *delayed_early_binding);
  
  END_EXTERN_C()