diff options
author | Dmitry Stogov <dmitry@zend.com> | 2019-02-14 13:12:50 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2019-02-14 13:12:50 +0300 |
commit | 43a7d95016761787cace63fb52e93e27e123d0cc (patch) | |
tree | 5c063c77d0ee0c0cc12e4ae15dc64602d216906c | |
parent | 8b6dba25c784ef9f190f84ced351d9ccc16f0a91 (diff) | |
download | php-git-43a7d95016761787cace63fb52e93e27e123d0cc.tar.gz |
Fixed bug #77613 (method visibility change) (reverted ZEND_ACC_CTOR and ZEND_ACC_DTOR flags removal)
-rw-r--r-- | UPGRADING.INTERNALS | 3 | ||||
-rw-r--r-- | Zend/tests/bug77613.phpt | 19 | ||||
-rw-r--r-- | Zend/zend_API.c | 2 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 2 | ||||
-rw-r--r-- | Zend/zend_compile.c | 2 | ||||
-rw-r--r-- | Zend/zend_compile.h | 6 | ||||
-rw-r--r-- | Zend/zend_inheritance.c | 9 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 10 |
8 files changed, 40 insertions, 13 deletions
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index e4147f249c..e190b291e9 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -38,9 +38,6 @@ PHP 7.4 INTERNALS UPGRADE NOTES instead of zval*. c. Function/property/class flags changes - - ZEND_ACC_CTOR and ZEND_ACC_DTOR are removed. It's possible to check if - method is a constructor/destructor using the following condition - (func->common.scope->constructor == func). - ZEND_ACC_IMPLEMENTED_ABSTRACT is removed (it was used only internally during inheritance). - ZEND_ACC_IMPLICIT_PUBLIC is removed (it was used only for reflection) diff --git a/Zend/tests/bug77613.phpt b/Zend/tests/bug77613.phpt new file mode 100644 index 0000000000..02d7ad4b72 --- /dev/null +++ b/Zend/tests/bug77613.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #77613 (method visibility change) +--FILE-- +<?php +class A { + public function __construct() { + static $foo; + } +} + +class B extends A { } + +class C extends B { + private function __construct() {} +} +?> +OK +--EXPECT-- +OK diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 60f0e29931..f191ca25b9 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2340,12 +2340,14 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio scope->__isset = __isset; scope->__debugInfo = __debugInfo; if (ctor) { + ctor->common.fn_flags |= ZEND_ACC_CTOR; if (ctor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name)); } ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } if (dtor) { + dtor->common.fn_flags |= ZEND_ACC_DTOR; if (dtor->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name)); } diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index ab365967bd..93bbd3bc87 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1291,7 +1291,7 @@ ZEND_FUNCTION(get_class_methods) if (!key) { ZVAL_STR_COPY(&method_name, mptr->common.function_name); zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name); - } else if (mptr->common.scope->constructor != mptr || + } else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 || mptr->common.scope == ce || zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cb961be234..03f8cf2563 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6270,6 +6270,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } if (ce->constructor) { + ce->constructor->common.fn_flags |= ZEND_ACC_CTOR; if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) { zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name)); @@ -6281,6 +6282,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */ } } if (ce->destructor) { + ce->destructor->common.fn_flags |= ZEND_ACC_DTOR; if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) { zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name)); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 84d6b9f7b3..d12199a6d6 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -316,6 +316,12 @@ typedef struct _zend_oparray_context { /* op_array is preloaded | | | */ #define ZEND_ACC_PRELOADED (1 << 27) /* | X | | */ /* | | | */ +/* functions is a constructor | | | */ +#define ZEND_ACC_CTOR (1 << 28) /* | X | | */ +/* | | | */ +/* function is a destructor | | | */ +#define ZEND_ACC_DTOR (1 << 29) /* | X | | */ +/* | | | */ /* op_array uses strict mode types | | | */ #define ZEND_ACC_STRICT_TYPES (1 << 31) /* | X | | */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 6a66846145..858a36213c 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -272,7 +272,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c /* Checks for constructors only if they are declared in an interface, * or explicitly marked as abstract */ - if ((fe->common.scope->constructor == fe) + if ((fe->common.fn_flags & ZEND_ACC_CTOR) && ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0 && (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) { return 1; @@ -574,7 +574,7 @@ static void do_inheritance_check_on_method(zend_function *child, zend_function * zend_function *proto = parent->common.prototype ? parent->common.prototype : parent; - if (parent->common.scope->constructor != parent) { + if (!(parent_flags & ZEND_ACC_CTOR)) { if (!proto) { proto = parent; } @@ -1322,10 +1322,11 @@ static void zend_add_magic_methods(zend_class_entry* ce, zend_string* mname, zen 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)) { + 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); } @@ -1986,7 +1987,7 @@ static void zend_verify_abstract_class_function(zend_function *fn, zend_abstract if (ai->cnt < MAX_ABSTRACT_INFO_CNT) { ai->afn[ai->cnt] = fn; } - if (fn->common.scope->constructor == fn) { + if (fn->common.fn_flags & ZEND_ACC_CTOR) { if (!ai->ctor) { ai->cnt++; ai->ctor = 1; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 1e11b8735a..8bfafe7c5a 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -485,7 +485,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char size_t len = ZSTR_LEN(mptr->common.function_name); /* Do not display old-style inherited constructors */ - if (mptr->common.scope->constructor != mptr + if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 || mptr->common.scope == ce || !key || zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0) @@ -756,10 +756,10 @@ static void _function_string(smart_str *str, zend_function *fptr, zend_class_ent if (fptr->common.prototype && fptr->common.prototype->common.scope) { smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name)); } - if (fptr->common.scope && fptr->common.scope->constructor == fptr) { + if (fptr->common.fn_flags & ZEND_ACC_CTOR) { smart_str_appends(str, ", ctor"); } - if (fptr->common.scope && fptr->common.scope->destructor == fptr) { + if (fptr->common.fn_flags & ZEND_ACC_DTOR) { smart_str_appends(str, ", dtor"); } smart_str_appends(str, "> "); @@ -3403,7 +3403,7 @@ ZEND_METHOD(reflection_method, isConstructor) /* we need to check if the ctor is the ctor of the class level we we * looking at since we might be looking at an inherited old style ctor * defined in base class. */ - RETURN_BOOL(intern->ce->constructor == mptr); + RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope); } /* }}} */ @@ -3418,7 +3418,7 @@ ZEND_METHOD(reflection_method, isDestructor) return; } GET_REFLECTION_OBJECT_PTR(mptr); - RETURN_BOOL(intern->ce->destructor == mptr); + RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR); } /* }}} */ |