diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/tests/bug78776.phpt | 28 | ||||
-rw-r--r-- | Zend/zend_inheritance.c | 15 |
3 files changed, 36 insertions, 9 deletions
@@ -8,6 +8,8 @@ PHP NEWS (Alexey Kachalin) . Fixed bug #78973 (Destructor during CV freeing causes segfault if opline never saved). (Nikita) + . Fixed bug #78776 (Abstract method implementation from trait does not check + "static"). (Nikita) - OPcache: . Fixed bug #78961 (erroneous optimization of re-assigned $GLOBALS). (Dmitry) diff --git a/Zend/tests/bug78776.phpt b/Zend/tests/bug78776.phpt new file mode 100644 index 0000000000..3696d955a3 --- /dev/null +++ b/Zend/tests/bug78776.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #78776: Abstract method implementation from trait does not check "static" +--FILE-- +<?php + +abstract class A +{ + abstract public function createApp(); +} + +class B extends A +{ + use C; +} + +trait C +{ + public static function createApp() + { + echo "You should not be here\n"; + } +} + +B::createApp(); + +?> +--EXPECTF-- +Fatal error: Cannot make non static method A::createApp() static in class C in %s on line %d diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index 0dbb5b77a6..9a11269801 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -812,7 +812,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(z parent = proto; } - if (!check_only && child_zv && child->common.prototype != proto) { + if (!check_only && child->common.prototype != proto) { do { if (child->common.scope != ce && child->type == ZEND_USER_FUNCTION @@ -820,7 +820,7 @@ static zend_always_inline inheritance_status do_inheritance_check_on_method_ex(z if (ce->ce_flags & ZEND_ACC_INTERFACE) { /* Few parent interfaces contain the same method */ break; - } else { + } else if (child_zv) { /* op_array wasn't duplicated yet */ zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); memcpy(new_function, child, sizeof(zend_op_array)); @@ -1585,17 +1585,14 @@ static void zend_add_trait_method(zend_class_entry *ce, const char *name, zend_s } zend_hash_update_mem(*overridden, key, fn, sizeof(zend_function)); return; - } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT && - (existing_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) { - /* Make sure the trait method is compatible with previosly declared abstract method */ - perform_delayable_implementation_check( - ce, fn, existing_fn, /*always_error*/ 1); - } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) { + } else if ((fn->common.fn_flags & ZEND_ACC_ABSTRACT) + && !(existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT)) { /* Make sure the abstract declaration is compatible with previous declaration */ perform_delayable_implementation_check( ce, existing_fn, fn, /*always_error*/ 1); return; - } else if (UNEXPECTED(existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT)) { + } else if (UNEXPECTED((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) + && !(existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT))) { /* two traits can't define the same non-abstract method */ #if 1 zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s", |