From 9397f527248a948e4d3929adb119e7e3519ce5b8 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Sat, 28 Nov 2015 23:38:19 -0800 Subject: [PATCH] Fixed Bug #70967 (Weird error handling for __toString when Error is thrown) --- NEWS | 2 ++ Zend/tests/bug26166.phpt | 4 ++-- Zend/tests/bug60909_2.phpt | 2 +- Zend/tests/bug70967.phpt | 14 ++++++++++++++ Zend/zend_object_handlers.c | 11 ++++++++++- ext/spl/tests/iterator_036.phpt | 2 +- tests/classes/tostring_003.phpt | 2 +- 7 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/bug70967.phpt diff --git a/NEWS b/NEWS index 7d7daaea55..5d7a185d33 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? 2015, PHP 7.0.1 - Core: + . Fixed bug #70967 (Weird error handling for __toString when Error is + thrown). (Laruence) . Fixed bug #70970 (Segfault when combining error handler with output buffering). (Laruence) . Fixed bug #70958 (Invalid opcode while using ::class as trait method diff --git a/Zend/tests/bug26166.phpt b/Zend/tests/bug26166.phpt index 9e31efa442..a77989c7c2 100644 --- a/Zend/tests/bug26166.phpt +++ b/Zend/tests/bug26166.phpt @@ -68,7 +68,7 @@ catch (Exception $e) { --EXPECTF-- Hello World! ===NONE=== -string(56) "Method NoneTest::__toString() must return a string value" +string(%d) "Method NoneTest::__toString() must return a string value" ===THROW=== -Fatal error: Method ErrorTest::__toString() must not throw an exception in %sbug26166.php on line %d +Fatal error: Method ErrorTest::__toString() must not throw an exception, caught Exception: This is an error! in %sbug26166.php on line %d diff --git a/Zend/tests/bug60909_2.phpt b/Zend/tests/bug60909_2.phpt index d08d9f90fa..1808b1c2fe 100644 --- a/Zend/tests/bug60909_2.phpt +++ b/Zend/tests/bug60909_2.phpt @@ -14,7 +14,7 @@ class Bad { $bad = new Bad(); echo "$bad"; --EXPECTF-- -Fatal error: Method Bad::__toString() must not throw an exception in %sbug60909_2.php on line 0 +Fatal error: Method Bad::__toString() must not throw an exception, caught Exception: Oops, I cannot do this in %sbug60909_2.php on line %d !!!shutdown!!! diff --git a/Zend/tests/bug70967.phpt b/Zend/tests/bug70967.phpt new file mode 100644 index 0000000000..89fc80b3f7 --- /dev/null +++ b/Zend/tests/bug70967.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #70967 (Weird error handling for __toString when Error is thrown) +--FILE-- + +--EXPECTF-- +Fatal error: Method A::__toString() must not throw an exception, caught Error: Call to undefined function undefined_function() in %sbug70967.php on line %d diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 4cd8a4e7c2..0b4f7d24e1 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1526,9 +1526,18 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty if (ce->__tostring && (zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) { if (UNEXPECTED(EG(exception) != NULL)) { + zval *msg, ex, rv; zval_ptr_dtor(&retval); + ZVAL_OBJ(&ex, EG(exception)); EG(exception) = NULL; - zend_error_noreturn(E_ERROR, "Method %s::__toString() must not throw an exception", ZSTR_VAL(ce->name)); + msg = zend_read_property(Z_OBJCE(ex), &ex, "message", sizeof("message") - 1, 1, &rv); + if (UNEXPECTED(Z_TYPE_P(msg) != IS_STRING)) { + ZVAL_EMPTY_STRING(&rv); + msg = &rv; + } + zend_error_noreturn(E_ERROR, + "Method %s::__toString() must not throw an exception, caught %s: %s", + ZSTR_VAL(ce->name), ZSTR_VAL(Z_OBJCE(ex)->name), Z_STRVAL_P(msg)); return FAILURE; } if (EXPECTED(Z_TYPE(retval) == IS_STRING)) { diff --git a/ext/spl/tests/iterator_036.phpt b/ext/spl/tests/iterator_036.phpt index 9a9e66b3b3..0f668db53f 100644 --- a/ext/spl/tests/iterator_036.phpt +++ b/ext/spl/tests/iterator_036.phpt @@ -19,4 +19,4 @@ test(new CachingIterator($ar, 0)); ===DONE=== --EXPECTF-- -Fatal error: Method CachingIterator::__toString() must not throw an exception in %siterator_036.php on line %d +Fatal error: Method CachingIterator::__toString() must not throw an exception, caught BadMethodCallException: CachingIterator does not fetch string value (see CachingIterator::__construct) in %siterator_036.php on line %d diff --git a/tests/classes/tostring_003.phpt b/tests/classes/tostring_003.phpt index 8815bd9407..096a7502fe 100644 --- a/tests/classes/tostring_003.phpt +++ b/tests/classes/tostring_003.phpt @@ -30,4 +30,4 @@ catch(Exception $e) ?> ====DONE==== --EXPECTF-- -Fatal error: Method Test::__toString() must not throw an exception in %stostring_003.php on line %d +Fatal error: Method Test::__toString() must not throw an exception, caught Exception: Damn! in %stostring_003.php on line %d -- 2.40.0