From 3c6c24b26b20f87b145c8798b5dde792eec16439 Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Mon, 6 Jan 2025 21:55:45 +0530 Subject: [PATCH] Allow Throwable to be extended outside of Exception Related to #17233 Allow `\Throwable` to be extended directly without causing a Fatal error. * **Zend/zend_exceptions.c** - Remove the restriction in `zend_implement_throwable` function that checks if a class implementing `\Throwable` extends `Exception` or `Error`. - Update the `zend_register_default_exception` function to register the `zend_ce_throwable` interface without the restriction. * **Zend/tests/bug_test.phpt** - Add a new test file to ensure that extending `\Throwable` directly works as expected. - Add a test case to check if a class can extend `\Throwable` directly without causing a Fatal error. - Add a test case to check if a class extending `\Throwable` directly can implement the required methods. --- Zend/tests/bug_test.phpt | 44 ++++++++++++++++++++++++++++++++++++++++ Zend/zend_exceptions.c | 22 +------------------- 2 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 Zend/tests/bug_test.phpt diff --git a/Zend/tests/bug_test.phpt b/Zend/tests/bug_test.phpt new file mode 100644 index 0000000000000..3486c4fe4eade --- /dev/null +++ b/Zend/tests/bug_test.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test extending \Throwable directly +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +MyThrowable message diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index c66509c50eaed..a544956943569 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -57,27 +57,7 @@ static zend_object_handlers default_exception_handlers; /* {{{ zend_implement_throwable */ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entry *class_type) { - /* zend_ce_exception and zend_ce_error may not be initialized yet when this is called (e.g when - * implementing Throwable for Exception itself). Perform a manual inheritance check. */ - zend_class_entry *root = class_type; - while (root->parent) { - root = root->parent; - } - if (zend_string_equals_literal(root->name, "Exception") - || zend_string_equals_literal(root->name, "Error")) { - return SUCCESS; - } - - bool can_extend = (class_type->ce_flags & ZEND_ACC_ENUM) == 0; - - zend_error_noreturn(E_ERROR, - can_extend - ? "%s %s cannot implement interface %s, extend Exception or Error instead" - : "%s %s cannot implement interface %s", - zend_get_object_type_uc(class_type), - ZSTR_VAL(class_type->name), - ZSTR_VAL(interface->name)); - return FAILURE; + return SUCCESS; } /* }}} */