]> granicus.if.org Git - php/commitdiff
Fixed Bug #70967 (Weird error handling for __toString when Error is thrown)
authorXinchen Hui <laruence@gmail.com>
Sun, 29 Nov 2015 07:38:19 +0000 (23:38 -0800)
committerXinchen Hui <laruence@gmail.com>
Sun, 29 Nov 2015 07:38:19 +0000 (23:38 -0800)
NEWS
Zend/tests/bug26166.phpt
Zend/tests/bug60909_2.phpt
Zend/tests/bug70967.phpt [new file with mode: 0644]
Zend/zend_object_handlers.c
ext/spl/tests/iterator_036.phpt
tests/classes/tostring_003.phpt

diff --git a/NEWS b/NEWS
index 7d7daaea55b0e80908ad445784f285514df1be3c..5d7a185d33fd89deb83d5c0d222909cec8137dba 100644 (file)
--- 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
index 9e31efa44259fc0b87ed53dd38efe390db98ab4f..a77989c7c2c82e6ab9b0d066a5eb14af1ac7f43a 100644 (file)
@@ -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
index d08d9f90fa25e6adba52dd81220394cfa3de9843..1808b1c2feb09c6c3a9f94219901022300f79ed7 100644 (file)
@@ -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 (file)
index 0000000..89fc80b
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Bug #70967 (Weird error handling for __toString when Error is thrown)
+--FILE--
+<?php
+class A {
+       public function __toString() {
+               undefined_function();
+       }
+}
+
+echo (new A);
+?>
+--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
index 4cd8a4e7c2aaa24d8585e76c3b269bf1d7a6706c..0b4f7d24e198cbe988d6360a3d736efa6bea2aee 100644 (file)
@@ -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)) {
index 9a9e66b3b3cec576c86f1700c9d8fb8495e72ad7..0f668db53f3c1ff870eea9e6ee62d2c0243fcdb4 100644 (file)
@@ -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
index 8815bd9407ff7fb7cb9734be9c40aedd897347c9..096a7502fe609eb51dce122c8ca05aff020b451b 100644 (file)
@@ -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