From 4a51ea4b81f2e3bc812ebd2b7ef9e6b4b295f1bf Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Mon, 15 Aug 2011 22:16:58 +0000 Subject: [PATCH] Bug #55424 Fatal error when calling a method from a trait that is defined in parent class and required by using an abstract method in the trait. # The method got unconditionally deleted from the class, since it was assumed that we override it, but we did not in case of abstract methods coming from a trait. Thus, dont delete when we try to merge in an abstract method. --- Zend/tests/traits/bug55424.phpt | 35 +++++++++++++++++++++++++++++++++ Zend/zend_compile.c | 11 +++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/traits/bug55424.phpt diff --git a/Zend/tests/traits/bug55424.phpt b/Zend/tests/traits/bug55424.phpt new file mode 100644 index 0000000000..b6c3b54515 --- /dev/null +++ b/Zend/tests/traits/bug55424.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug #55424 (Method got missing from class when a trait defined an abstract method to express a requirement) +--FILE-- +setAttribute(); + } + + abstract function setAttribute(); + } + + class Base + { + function setAttribute() { } + } + + class MyClass extends Base + { + use ATrait; + } + + $i = new Base(); + $i->setAttribute(); + + $t = new MyClass(); + /* setAttribute used to disappear for no good reason. */ + $t->setRequired(); + echo 'DONE'; +?> +--EXPECT-- +DONE diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 59e0193194..cd883cbe6f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3635,10 +3635,13 @@ static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int } else if (existing_fn->common.scope != ce) { add = 1; /* or inherited from other class or interface */ /* it is just a reference which was added to the subclass while doing the inheritance */ - /* prototype = existing_fn; */ - /* memory is scrambled anyway???? */ - /* function_add_ref(prototype); */ - zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h); + /* so we can deleted now, and will add the overriding method afterwards */ + + /* except, if we try to add an abstract function, then we should not delete the inherited one */ + /* delete inherited fn if the function to be added is not abstract */ + if ((fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) { + zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h); + } } if (add) { -- 2.40.0