]> granicus.if.org Git - php/commitdiff
Allow exceptions in __toString()
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 26 Feb 2019 14:32:18 +0000 (15:32 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 5 Jun 2019 12:25:07 +0000 (14:25 +0200)
RFC: https://wiki.php.net/rfc/tostring_exceptions

And convert some object to string conversion related recoverable
fatal errors into Error exceptions.

Improve exception safety of internal code performing string
conversions.

113 files changed:
UPGRADING
UPGRADING.INTERNALS
Zend/tests/bug26166.phpt
Zend/tests/bug28444.phpt
Zend/tests/bug30791.phpt
Zend/tests/bug60909_2.phpt
Zend/tests/bug70967.phpt
Zend/tests/bug72162.phpt
Zend/tests/call_with_refs.phpt
Zend/tests/class_properties_const.phpt
Zend/tests/closure_015.phpt
Zend/tests/exception_009.phpt
Zend/tests/exception_from_toString.phpt [new file with mode: 0644]
Zend/tests/instanceof_001.phpt
Zend/tests/unexpected_ref_bug.phpt
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_execute.c
Zend/zend_object_handlers.c
Zend/zend_operators.c
Zend/zend_operators.h
Zend/zend_string.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/date/php_date.c
ext/dba/dba.c
ext/dom/attr.c
ext/dom/characterdata.c
ext/dom/document.c
ext/dom/node.c
ext/dom/processinginstruction.c
ext/dom/tests/toString_exceptions.phpt [new file with mode: 0644]
ext/exif/exif.c
ext/gd/gd.c
ext/iconv/iconv.c
ext/imap/php_imap.c
ext/intl/dateformat/dateformat_format_object.cpp
ext/intl/timezone/timezone_class.cpp
ext/intl/timezone/timezone_methods.cpp
ext/intl/transliterator/transliterator_class.c
ext/intl/transliterator/transliterator_methods.c
ext/libxml/libxml.c
ext/mbstring/mbstring.c
ext/mbstring/php_mbregex.c
ext/mysqli/mysqli.c
ext/mysqli/mysqli_api.c
ext/mysqlnd/mysqlnd_ps_codec.c
ext/oci8/oci8_statement.c
ext/odbc/php_odbc.c
ext/openssl/openssl.c
ext/openssl/tests/bug38261.phpt
ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt
ext/openssl/xp_ssl.c
ext/pcntl/pcntl.c
ext/pcre/php_pcre.c
ext/pcre/tests/preg_replace_error1.phpt
ext/pcre/tests/preg_replace_error2.phpt
ext/pdo/pdo_sql_parser.re
ext/pdo/pdo_stmt.c
ext/pdo/php_pdo_driver.h
ext/pdo_firebird/firebird_driver.c
ext/pdo_firebird/firebird_statement.c
ext/pdo_oci/oci_driver.c
ext/pdo_oci/oci_statement.c
ext/pdo_pgsql/pgsql_driver.c
ext/pdo_sqlite/sqlite_driver.c
ext/pdo_sqlite/sqlite_statement.c
ext/pdo_sqlite/tests/pdo_sqlite_tostring_exception.phpt [new file with mode: 0644]
ext/pgsql/pgsql.c
ext/readline/readline.c
ext/reflection/php_reflection.c
ext/reflection/tests/bug74673.phpt
ext/session/session.c
ext/simplexml/simplexml.c
ext/snmp/snmp.c
ext/sockets/conversions.c
ext/spl/spl_iterators.c
ext/spl/tests/iterator_036.phpt
ext/spl/tests/recursive_tree_iterator_007.phpt
ext/sqlite3/sqlite3.c
ext/sqlite3/tests/exception_from_toString.phpt [new file with mode: 0644]
ext/standard/array.c
ext/standard/assert.c
ext/standard/basic_functions.c
ext/standard/filters.c
ext/standard/formatted_print.c
ext/standard/head.c
ext/standard/math.c
ext/standard/pack.c
ext/standard/password.c
ext/standard/proc_open.c
ext/standard/streamsfuncs.c
ext/standard/string.c
ext/standard/tests/array/array_multisort_variation8.phpt
ext/standard/tests/class_object/get_class_methods_variation_001.phpt
ext/standard/tests/class_object/get_parent_class_variation_002.phpt
ext/standard/tests/general_functions/type.phpt
ext/standard/tests/math/base_convert_error.phpt
ext/standard/tests/streams/bug61115.phpt
ext/standard/tests/strings/strval_error.phpt
ext/standard/var.c
ext/xml/xml.c
ext/xmlreader/php_xmlreader.c
ext/xmlrpc/xmlrpc-epi-php.c
ext/xsl/xsltprocessor.c
ext/zip/php_zip.c
ext/zlib/zlib.c
main/streams/userspace.c
tests/classes/tostring_001.phpt
tests/classes/tostring_003.phpt
tests/classes/tostring_004.phpt
win32/codepage.c

index 2d63688969afa371ce3aea74de9604f2fbd1737b..49e4edf40e850aaf50d8cb00ce9019fc2677b99f 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -187,6 +187,11 @@ PHP 7.4 UPGRADE NOTES
   . Support for WeakReferences has been added.
     RFC: https://wiki.php.net/rfc/weakrefs
 
+  . Throwing exceptions from __toString() is now permitted. Previously this
+    resulted in a fatal error. Existing recoverable fatals in string conversions
+    have been converted to Error exceptions.
+    RFC: https://wiki.php.net/rfc/tostring_exceptions
+
 - CURL:
   . CURLFile now supports stream wrappers in addition to plain file names, if
     the extension has been built against libcurl >= 7.56.0.  The streams may
index 6cd3463ef2451116d3b1da063f02e4744c0ef0cf..b53745b0f00e51b41eef7483ce20422134d0f29f 100644 (file)
@@ -19,6 +19,8 @@ PHP 7.4 INTERNALS UPGRADE NOTES
   p. ZEND_EXT_FCALL_BEGIN can access arguments
   q. ZEND_COMPILE_IGNORE_USER_FUNCTIONS and ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS
   r. TSRM environment locking
+  s. Typed references support
+  t. Exceptions thrown by string conversions.
 
 2. Build system changes
   a. Abstract
@@ -198,6 +200,14 @@ PHP 7.4 INTERNALS UPGRADE NOTES
      behave as if they are safe, care should still be taken in multi-threaded
      environments.
 
+  s. Correct support for typed properties requires the use of new macros to
+     assign values to references. For more information see
+     https://wiki.php.net/rfc/typed_properties_v2#impact_on_extensions.
+
+  t. convert_to_string() and zval_get_string() are now more likely to result in
+     an exception. For instructions on how to gracefully handle this see
+     https://wiki.php.net/rfc/tostring_exceptions#extension_guidelines.
+
 ========================
 2. Build system changes
 ========================
index a77989c7c2c82e6ab9b0d066a5eb14af1ac7f43a..7a3be86c3fa68b2be8fa515c4501cca7eeecd462 100644 (file)
@@ -31,12 +31,6 @@ echo $o;
 
 echo "===NONE===\n";
 
-function my_error_handler($errno, $errstr, $errfile, $errline) {
-       var_dump($errstr);
-}
-
-set_error_handler('my_error_handler');
-
 class NoneTest
 {
        function __toString() {
@@ -44,7 +38,11 @@ class NoneTest
 }
 
 $o = new NoneTest;
-echo $o;
+try {
+    echo $o;
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 echo "===THROW===\n";
 
@@ -58,17 +56,16 @@ class ErrorTest
 $o = new ErrorTest;
 try {
        echo $o;
-}
-catch (Exception $e) {
-       echo "Got the exception\n";
+} catch (Exception $e) {
+       echo $e->getMessage(), "\n";
 }
 
 ?>
 ===DONE===
---EXPECTF--
+--EXPECT--
 Hello World!
 ===NONE===
-string(%d) "Method NoneTest::__toString() must return a string value"
+Method NoneTest::__toString() must return a string value
 ===THROW===
-
-Fatal error: Method ErrorTest::__toString() must not throw an exception, caught Exception: This is an error! in %sbug26166.php on line %d
+This is an error!
+===DONE===
index b7e863da9205194cc3af73646a34593e81780a1c..464aaef4c7972a86e6bc4db1f293562d1256dd18 100644 (file)
@@ -3,12 +3,6 @@ Bug #28444 (Cannot access undefined property for object with overloaded property
 --FILE--
 <?php
 
-function my_error_handler($errno, $errstr, $errfile, $errline) {
-       var_dump($errstr);
-}
-
-set_error_handler('my_error_handler');
-
 class ObjectOne
 {
        public $x;
@@ -17,6 +11,10 @@ class ObjectOne
        {
                $this->x = $x;
        }
+
+       function __toString() {
+               return "Object";
+       }
 }
 
 class Overloaded
@@ -55,8 +53,8 @@ var_dump($y->z->x = 6);
 
 ?>
 ===DONE===
---EXPECTF--
-object(ObjectOne)#%d (1) {
+--EXPECT--
+object(ObjectOne)#2 (1) {
   ["x"]=>
   int(2)
 }
@@ -66,9 +64,8 @@ Overloaded::__set(y,3)
 int(3)
 Overloaded::__get(y)
 int(3)
-string(58) "Object of class ObjectOne could not be converted to string"
-Overloaded::__set(z,)
-object(ObjectOne)#%d (1) {
+Overloaded::__set(z,Object)
+object(ObjectOne)#3 (1) {
   ["x"]=>
   int(4)
 }
index e9991f3ad5da252f5089b1c07916d431ce6fea04..1b3b2ffe243010e25fb4a0c75f2ffce14cfa04db 100644 (file)
@@ -3,32 +3,25 @@ Bug #30791 (magic methods (__sleep/__wakeup/__toString) call __call if object is
 --FILE--
 <?php
 
-function my_error_handler($errno, $errstr, $errfile, $errline) {
-       var_dump($errstr);
-}
-
-set_error_handler('my_error_handler');
-
 class a
 {
-   public $a = 4;
-   function __call($a,$b) {
-       return "unknown method";
-   }
+    public $a = 4;
+    function __call($name, $args) {
+        echo __METHOD__, "\n";
+    }
 }
 
 $b = new a;
-echo $b,"\n";
+var_dump($b);
 $c = unserialize(serialize($b));
-echo $c,"\n";
 var_dump($c);
 
 ?>
 --EXPECT--
-string(50) "Object of class a could not be converted to string"
-
-string(50) "Object of class a could not be converted to string"
-
+object(a)#1 (1) {
+  ["a"]=>
+  int(4)
+}
 object(a)#2 (1) {
   ["a"]=>
   int(4)
index 1808b1c2feb09c6c3a9f94219901022300f79ed7..9660a9653fa57859465707a4bf9160a4a5cb00bb 100644 (file)
@@ -3,18 +3,21 @@ Bug #60909 (custom error handler throwing Exception + fatal error = no shutdown
 --FILE--
 <?php
 register_shutdown_function(function(){echo("\n\n!!!shutdown!!!\n\n");});
-set_error_handler(function($errno, $errstr, $errfile, $errline){throw new Exception("Foo");});
 
 class Bad {
     public function __toString() {
-        throw new Exception('Oops, I cannot do this');
+        throw new Exception('I CAN DO THIS');
     }
 }
 
 $bad = new Bad();
 echo "$bad";
 --EXPECTF--
-Fatal error: Method Bad::__toString() must not throw an exception, caught Exception: Oops, I cannot do this in %sbug60909_2.php on line %d
+Fatal error: Uncaught Exception: I CAN DO THIS in %s:%d
+Stack trace:
+#0 %s(%d): Bad->__toString()
+#1 {main}
+  thrown in %s on line %d
 
 
 !!!shutdown!!!
index 89fc80b3f7e796f6ba1aa8130e4d6fd91d455d92..d254ea8d89c9f7cf1556ffac22ab1329b9629df2 100644 (file)
@@ -11,4 +11,8 @@ class A {
 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
+Fatal error: Uncaught Error: Call to undefined function undefined_function() in %s:%d
+Stack trace:
+#0 %s(%d): A->__toString()
+#1 {main}
+  thrown in %s on line %d
index 493342d8388f340f1d261fec65a23caceb7e6f4c..44237038a12b81a9c1a9debf4c4d840b0de6899b 100644 (file)
@@ -7,4 +7,8 @@ $var11 = new StdClass();
 $var16 = error_reporting($var11);
 ?>
 --EXPECTF--
-Recoverable fatal error: Object of class stdClass could not be converted to string in %sbug72162.php on line %d
+Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in %s:%d
+Stack trace:
+#0 %s(%d): error_reporting(Object(stdClass))
+#1 {main}
+  thrown in %s on line %d
index f7b18365b4a5d71e59c92838ff16b602234abef5..0e01779a2128dfcd0fd2b3847962eb9c3ca423e8 100644 (file)
@@ -2,16 +2,17 @@
 Check call to non-ref function with call-time refs
 --FILE--
 <?php
-function my_errorhandler($errno,$errormsg) {
-  global $my_var;
-  $my_var=0x12345;
-  echo $errormsg."\n";
-  return true;
+class Test {
+    public function __toString() {
+        global $my_var;
+        $my_var=0x12345;
+        return "";
+    }
 }
-$oldhandler = set_error_handler("my_errorhandler");
+
 $my_var = str_repeat("A",64);
-$data = call_user_func_array("substr_replace",array(&$my_var, new StdClass(),1));
+$data = call_user_func_array("substr_replace",array(&$my_var, new Test(), 1));
 echo "OK!";
+?>
 --EXPECT--
-Object of class stdClass could not be converted to string
 OK!
index 8f607bcfe20698a21d0db806b530c9d1cd248186..6f5471d20a62ac6e9b9b1332069784e12f7b3f48 100644 (file)
@@ -22,4 +22,7 @@ NULL
 Notice: Undefined property: A::$1 in %sclass_properties_const.php on line %d
 NULL
 
-Recoverable fatal error: Object of class Closure could not be converted to string in %sclass_properties_const.php on line %d
+Fatal error: Uncaught Error: Object of class Closure could not be converted to string in %s:%d
+Stack trace:
+#0 {main}
+  thrown in %s on line %d
index 33c732d72372257fe9f12ae8a494186132b4e914..f6903ebdb183d0245ad9df1313943cc0cfe19051 100644 (file)
@@ -2,18 +2,20 @@
 Closure 015: converting to string/unicode
 --FILE--
 <?php
-set_error_handler('myErrorHandler', E_RECOVERABLE_ERROR);
-function myErrorHandler($errno, $errstr, $errfile, $errline) {
-  echo "Error: $errstr at $errfile($errline)\n";
-  return true;
-}
+
 $x = function() { return 1; };
-print (string) $x;
-print "\n";
-print $x;
-print "\n";
-?>
---EXPECTF--
-Error: Object of class Closure could not be converted to string at %sclosure_015.php(8)
+try {
+    print (string) $x;
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    print $x;
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
-Error: Object of class Closure could not be converted to string at %sclosure_015.php(10)
+?>
+--EXPECT--
+Object of class Closure could not be converted to string
+Object of class Closure could not be converted to string
index 32b048c40b267131f681e0c61fd635f492da2601..340bd99eb0c2ca5ca0c5becf3ad2f57e832abfdc 100644 (file)
@@ -25,4 +25,8 @@ throw new my_exception;
 
 ?>
 --EXPECT--
-Recoverable fatal error: Object of class stdClass could not be converted to string in Unknown on line 0
+Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in [no active file]:0
+Stack trace:
+#0 [internal function]: Exception->__toString()
+#1 {main}
+  thrown in [no active file] on line 0
diff --git a/Zend/tests/exception_from_toString.phpt b/Zend/tests/exception_from_toString.phpt
new file mode 100644 (file)
index 0000000..ee6dde9
--- /dev/null
@@ -0,0 +1,135 @@
+--TEST--
+Test exceptions thrown from __toString() in various contexts
+--FILE--
+<?php
+
+class BadStr {
+    public function __toString() {
+        throw new Exception("Exception");
+    }
+}
+
+$str = "a";
+$num = 42;
+$badStr = new BadStr;
+
+try { $x = $str . $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = $badStr . $str; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = $str .= $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump($str); 
+try { $x = $num . $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = $badStr . $num; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = $num .= $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump($num);
+
+try { $x = $badStr .= $str; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump($badStr);
+try { $x = $badStr .= $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump($badStr);
+
+try { $x = "x$badStr"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = "{$badStr}x"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = "$str$badStr"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = "$badStr$str"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+try { $x = "x$badStr$str"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = "x$str$badStr"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = "{$str}x$badStr"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+try { $x = "{$badStr}x$str"; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+try { $x = (string) $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+try { $x = include $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+try { echo $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+${""} = 42;
+try { unset(${$badStr}); }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump(${""});
+
+unset(${""});
+try { $x = ${$badStr}; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+try { $x = isset(${$badStr}); }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+
+$obj = new stdClass;
+try { $x = $obj->{$badStr} = $str; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump($obj);
+
+try { $str[0] = $badStr; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump($str);
+
+$obj = new DateInterval('P1D');
+try { $x = $obj->{$badStr} = $str; }
+catch (Exception $e) { echo $e->getMessage(), "\n"; }
+var_dump(!isset($obj->{""}));
+
+try { strlen($badStr); } catch (Exception $e) { echo "Exception\n"; }
+try { substr($badStr, 0); } catch (Exception $e) { echo "Exception\n"; }
+try { new ArrayObject([], 0, $badStr); } catch (Exception $e) { echo "Exception\n"; }
+
+?>
+--EXPECT--
+Exception
+Exception
+Exception
+string(1) "a"
+Exception
+Exception
+Exception
+int(42)
+Exception
+object(BadStr)#1 (0) {
+}
+Exception
+object(BadStr)#1 (0) {
+}
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+int(42)
+Exception
+Exception
+Exception
+object(stdClass)#2 (0) {
+}
+Exception
+string(1) "a"
+Exception
+bool(true)
+Exception
+Exception
+Exception
index 8c13a0478c1dc3c8fe77acb56189dcc9a993855c..6bdcb896aff78d43852b5322e8be59e346ddd8f2 100644 (file)
@@ -16,8 +16,6 @@ var_dump($c[0] instanceof stdClass);
 
 var_dump(@$inexistent instanceof stdClass);
 
-var_dump("$a" instanceof stdClass);
-
 ?>
 --EXPECTF--
 bool(true)
@@ -27,5 +25,3 @@ Deprecated: Function create_function() is deprecated in %s on line %d
 bool(true)
 bool(true)
 bool(false)
-
-Recoverable fatal error: Object of class stdClass could not be converted to string in %s on line %d
index ba61ee582addf5e6608cbb8527a6ea395c72e65e..c7f66f05a00f2c4b82e7b3ef55ed8dcdbe87af35 100644 (file)
@@ -2,16 +2,17 @@
 Crash when function parameter modified via unexpected reference
 --FILE--
 <?php
-function my_errorhandler($errno,$errormsg) {
-  global $my_var;
-  $my_var = 0;
-  return true;
+class Test {
+    public function __toString() {
+        global $my_var;
+        $my_var = 0;
+        return ",";
+    }
 }
-set_error_handler("my_errorhandler");
 $my_var = str_repeat("A",64);
-$data = call_user_func_array("explode",array(new StdClass(), &$my_var));
+$data = call_user_func_array("explode",array(new Test(), &$my_var));
 $my_var=array(1,2,3);
-$data = call_user_func_array("implode",array(&$my_var, new StdClass()));
+$data = call_user_func_array("implode",array(&$my_var, new Test()));
 echo "Done.\n";
 ?>
 --EXPECT--
index 10b47a19195843e49901568db2ea8f5410153698..f88fc2caf83d956bce9a53d0c7a78f9afb7b79f4 100644 (file)
@@ -334,7 +334,11 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc
                *pce = NULL;
                return 1;
        }
-       convert_to_string_ex(arg);
+       if (!try_convert_to_string(arg)) {
+               *pce = NULL;
+               return 0;
+       }
+
        *pce = zend_lookup_class(Z_STR_P(arg));
        if (ce_base) {
                if ((!*pce || !instanceof_function(*pce, ce_base))) {
@@ -731,7 +735,11 @@ static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, cons
                                        *pce = NULL;
                                        break;
                                }
-                               convert_to_string_ex(arg);
+                               if (!try_convert_to_string(arg)) {
+                                       *pce = NULL;
+                                       return "valid class name";
+                               }
+
                                if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
                                        *pce = NULL;
                                } else {
@@ -817,6 +825,9 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec
 
        expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity);
        if (expected_type) {
+               if (EG(exception)) {
+                       return FAILURE;
+               }
                if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
                        const char *space;
                        const char *class_name = get_active_class_name(&space);
@@ -3218,7 +3229,7 @@ try_again:
                        }
 
                        if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) {
-                               return zend_string_init("Array", sizeof("Array")-1, 0);
+                               return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
                        }
 
                        if (Z_TYPE_P(obj) == IS_STRING) {
@@ -3226,7 +3237,7 @@ try_again:
                        } else if (Z_TYPE_P(obj) == IS_OBJECT) {
                                return zend_create_method_string(Z_OBJCE_P(obj)->name, Z_STR_P(method));
                        } else {
-                               return zend_string_init("Array", sizeof("Array")-1, 0);
+                               return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
                        }
                }
                case IS_OBJECT:
index e8fa6e1e62ba06d529e6ed33d2c8941c60b540f1..473217365420e69bfb746128db2696794e938968 100644 (file)
@@ -1136,7 +1136,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha
                int _min_num_args = (min_num_args); \
                int _max_num_args = (max_num_args); \
                int _num_args = EX_NUM_ARGS(); \
-               int _i; \
+               int _i = 0; \
                zval *_real_arg, *_arg = NULL; \
                zend_expected_type _expected_type = Z_EXPECTED_LONG; \
                char *_error = NULL; \
@@ -1165,7 +1165,6 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha
                                _error_code = ZPP_ERROR_FAILURE; \
                                break; \
                        } \
-                       _i = 0; \
                        _real_arg = ZEND_CALL_ARG(execute_data, 0);
 
 #define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
@@ -1181,7 +1180,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha
 #define ZEND_PARSE_PARAMETERS_END_EX(failure) \
                } while (0); \
                if (UNEXPECTED(_error_code != ZPP_ERROR_OK)) { \
-                       if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
+                       if (!(_flags & ZEND_PARSE_PARAMS_QUIET) && !EG(exception)) { \
                                if (_error_code == ZPP_ERROR_WRONG_CALLBACK) { \
                                        if (_flags & ZEND_PARSE_PARAMS_THROW) { \
                                                zend_wrong_callback_exception(_i, _error); \
index 5333e3e315c8ffea305457a75b4bd922f2c36579..160fb8a73973b32cec6f656040176af02d922ce4 100644 (file)
@@ -737,6 +737,10 @@ ZEND_FUNCTION(error_reporting)
        old_error_reporting = EG(error_reporting);
        if (ZEND_NUM_ARGS() != 0) {
                zend_string *new_val = zval_get_string(err);
+               if (UNEXPECTED(EG(exception))) {
+                       return;
+               }
+
                do {
                        zend_ini_entry *p = EG(error_reporting_ini_entry);
 
index 96d1f614e33997d28bb03bc2ffd11d8b35a6025d..8adb6ef3b90b6be096a5f05f685647151ecdb0d1 100644 (file)
@@ -1549,6 +1549,12 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
        if (Z_TYPE_P(value) != IS_STRING) {
                /* Convert to string, just the time to pick the 1st byte */
                zend_string *tmp = zval_get_string_func(value);
+               if (UNEXPECTED(EG(exception))) {
+                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                               ZVAL_UNDEF(EX_VAR(opline->result.var));
+                       }
+                       return;
+               }
 
                string_len = ZSTR_LEN(tmp);
                c = (zend_uchar)ZSTR_VAL(tmp)[0];
@@ -4024,6 +4030,9 @@ static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval
        if (Z_TYPE_P(inc_filename) != IS_STRING) {
                ZVAL_STR(&tmp_inc_filename, zval_get_string_func(inc_filename));
                inc_filename = &tmp_inc_filename;
+               if (UNEXPECTED(EG(exception))) {
+                       return NULL;
+               }
        }
 
        switch (type) {
index 41042941c7558b334606b479bd433fb1f9310dc6..10f5ac1524350d8de9e26d449530bb4d11a77e62 100644 (file)
@@ -657,7 +657,10 @@ ZEND_API zval *zend_std_read_property(zval *object, zval *member, int type, void
        uint32_t *guard = NULL;
 
        zobj = Z_OBJ_P(object);
-       name = zval_get_tmp_string(member, &tmp_name);
+       name = zval_try_get_tmp_string(member, &tmp_name);
+       if (UNEXPECTED(!name)) {
+               return &EG(uninitialized_zval);
+       }
 
 #if DEBUG_OBJECT_HANDLERS
        fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
@@ -802,7 +805,10 @@ ZEND_API zval *zend_std_write_property(zval *object, zval *member, zval *value,
        ZEND_ASSERT(!Z_ISREF_P(value));
 
        zobj = Z_OBJ_P(object);
-       name = zval_get_tmp_string(member, &tmp_name);
+       name = zval_try_get_tmp_string(member, &tmp_name);
+       if (UNEXPECTED(!name)) {
+               return value;
+       }
 
        property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__set != NULL), cache_slot, &prop_info);
 
@@ -1011,7 +1017,10 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int typ
        zend_property_info *prop_info = NULL;
 
        zobj = Z_OBJ_P(object);
-       name = zval_get_tmp_string(member, &tmp_name);
+       name = zval_try_get_tmp_string(member, &tmp_name);
+       if (UNEXPECTED(!name)) {
+               return NULL;
+       }
 
 #if DEBUG_OBJECT_HANDLERS
        fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), ZSTR_VAL(name));
@@ -1073,7 +1082,10 @@ ZEND_API void zend_std_unset_property(zval *object, zval *member, void **cache_s
        zend_property_info *prop_info = NULL;
 
        zobj = Z_OBJ_P(object);
-       name = zval_get_tmp_string(member, &tmp_name);
+       name = zval_try_get_tmp_string(member, &tmp_name);
+       if (UNEXPECTED(!name)) {
+               return;
+       }
 
        property_offset = zend_get_property_offset(zobj->ce, name, (zobj->ce->__unset != NULL), cache_slot, &prop_info);
 
@@ -1640,7 +1652,10 @@ ZEND_API int zend_std_has_property(zval *object, zval *member, int has_set_exist
        zend_property_info *prop_info = NULL;
 
        zobj = Z_OBJ_P(object);
-       name = zval_get_tmp_string(member, &tmp_name);
+       name = zval_try_get_tmp_string(member, &tmp_name);
+       if (UNEXPECTED(!name)) {
+               return 0;
+       }
 
        property_offset = zend_get_property_offset(zobj->ce, name, 1, cache_slot, &prop_info);
 
@@ -1745,31 +1760,15 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
        switch (type) {
                case IS_STRING:
                        ce = Z_OBJCE_P(readobj);
-                       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;
-                                       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 (ce->__tostring) {
+                               zend_call_method_with_0_params(readobj, ce, &ce->__tostring, "__tostring", &retval);
                                if (EXPECTED(Z_TYPE(retval) == IS_STRING)) {
                                        ZVAL_COPY_VALUE(writeobj, &retval);
                                        return SUCCESS;
-                               } else {
-                                       zval_ptr_dtor(&retval);
-                                       ZVAL_EMPTY_STRING(writeobj);
-                                       zend_error(E_RECOVERABLE_ERROR, "Method %s::__toString() must return a string value", ZSTR_VAL(ce->name));
-                                       return SUCCESS;
+                               }
+                               zval_ptr_dtor(&retval);
+                               if (!EG(exception)) {
+                                       zend_throw_error(NULL, "Method %s::__toString() must return a string value", ZSTR_VAL(ce->name));
                                }
                        }
                        return FAILURE;
index 7b25eb1d52be4264edc3271efc678ce57a2ed9c1..896f6dcbe19e788bcd918f6ac105364219b8ad37 100644 (file)
@@ -568,19 +568,33 @@ try_again:
                case IS_ARRAY:
                        zend_error(E_NOTICE, "Array to string conversion");
                        zval_ptr_dtor(op);
-                       ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0));
+                       ZVAL_INTERNED_STR(op, ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED));
                        break;
                case IS_OBJECT: {
-                       zval dst;
-
-                       convert_object_to_type(op, &dst, IS_STRING, convert_to_string);
-                       zval_ptr_dtor(op);
+                       zval tmp;
 
-                       if (Z_TYPE(dst) == IS_STRING) {
-                               ZVAL_COPY_VALUE(op, &dst);
-                       } else {
-                               ZVAL_NEW_STR(op, zend_string_init("Object", sizeof("Object")-1, 0));
+                       if (Z_OBJ_HT_P(op)->cast_object) {
+                               if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING) == SUCCESS) {
+                                       zval_ptr_dtor(op);
+                                       ZVAL_COPY_VALUE(op, &tmp);
+                                       return;
+                               }
+                       } else if (Z_OBJ_HT_P(op)->get) {
+                               zval *z = Z_OBJ_HT_P(op)->get(op, &tmp);
+                               if (Z_TYPE_P(z) != IS_OBJECT) {
+                                       zend_string *str = zval_get_string(z);
+                                       zval_ptr_dtor(z);
+                                       zval_ptr_dtor(op);
+                                       ZVAL_STR(op, str);
+                                       return;
+                               }
+                               zval_ptr_dtor(z);
                        }
+                       if (!EG(exception)) {
+                               zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
+                       }
+                       zval_ptr_dtor(op);
+                       ZVAL_EMPTY_STRING(op);
                        break;
                }
                case IS_REFERENCE:
@@ -591,6 +605,19 @@ try_again:
 }
 /* }}} */
 
+ZEND_API zend_bool ZEND_FASTCALL _try_convert_to_string(zval *op)
+{
+       if (Z_TYPE_P(op) != IS_STRING) {
+               zend_string *str = zval_get_string_func(op);
+               if (UNEXPECTED(EG(exception))) {
+                       return 0;
+               }
+               zval_ptr_dtor(op);
+               ZVAL_STR(op, str);
+       }
+       return 1;
+}
+
 static void convert_scalar_to_array(zval *op) /* {{{ */
 {
        HashTable *ht = zend_new_array(1);
@@ -859,7 +886,7 @@ try_again:
                }
                case IS_ARRAY:
                        zend_error(E_NOTICE, "Array to string conversion");
-                       return zend_string_init("Array", sizeof("Array")-1, 0);
+                       return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
                case IS_OBJECT: {
                        zval tmp;
                        if (Z_OBJ_HT_P(op)->cast_object) {
@@ -875,7 +902,9 @@ try_again:
                                }
                                zval_ptr_dtor(z);
                        }
-                       zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
+                       if (!EG(exception)) {
+                               zend_throw_error(NULL, "Object of class %s could not be converted to string", ZSTR_VAL(Z_OBJCE_P(op)->name));
+                       }
                        return ZSTR_EMPTY_ALLOC();
                }
                case IS_REFERENCE:
@@ -889,6 +918,16 @@ try_again:
 }
 /* }}} */
 
+ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(zval *op) /* {{{ */
+{
+       zend_string *str = zval_get_string_func(op);
+       if (UNEXPECTED(EG(exception))) {
+               return NULL;
+       }
+       return str;
+}
+/* }}} */
+
 static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
 {
        if ((result == op1) && (result == op2)) {
index 1effdd6c674be4f65c7b8f644078d2680074b2a9..458ca66e2e95464e203e439d2f9d7163fd29ad5b 100644 (file)
@@ -258,6 +258,7 @@ ZEND_API void multi_convert_to_string_ex(int argc, ...);
 ZEND_API zend_long    ZEND_FASTCALL zval_get_long_func(zval *op);
 ZEND_API double       ZEND_FASTCALL zval_get_double_func(zval *op);
 ZEND_API zend_string* ZEND_FASTCALL zval_get_string_func(zval *op);
+ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(zval *op);
 
 static zend_always_inline zend_long zval_get_long(zval *op) {
        return EXPECTED(Z_TYPE_P(op) == IS_LONG) ? Z_LVAL_P(op) : zval_get_long_func(op);
@@ -283,6 +284,35 @@ static zend_always_inline void zend_tmp_string_release(zend_string *tmp) {
        }
 }
 
+/* Like zval_get_string, but returns NULL if the conversion fails with an exception. */
+static zend_always_inline zend_string *zval_try_get_string(zval *op) {
+       if (EXPECTED(Z_TYPE_P(op) == IS_STRING)) {
+               return Z_STR_P(op);
+       } else {
+               return zval_try_get_string_func(op);
+       }
+}
+
+/* Like zval_get_tmp_string, but returns NULL if the conversion fails with an exception. */
+static zend_always_inline zend_string *zval_try_get_tmp_string(zval *op, zend_string **tmp) {
+       if (EXPECTED(Z_TYPE_P(op) == IS_STRING)) {
+               *tmp = NULL;
+               return Z_STR_P(op);
+       } else {
+               return *tmp = zval_try_get_string_func(op);
+       }
+}
+
+/* Like convert_to_string(), but returns whether the conversion succeeded and does not modify the
+ * zval in-place if it fails. */
+ZEND_API zend_bool ZEND_FASTCALL _try_convert_to_string(zval *op);
+static zend_always_inline zend_bool try_convert_to_string(zval *op) {
+       if (Z_TYPE_P(op) == IS_STRING) {
+               return 1;
+       }
+       return _try_convert_to_string(op);
+}
+
 /* Compatibility macros for 7.2 and below */
 #define _zval_get_long(op) zval_get_long(op)
 #define _zval_get_double(op) zval_get_double(op)
index 20275f330a98c855444dc2c17ff3e535e9c812f1..b4a0ddef958f917bd323d1133c6c425160c5e4f2 100644 (file)
@@ -506,6 +506,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
        _(ZEND_STR_NAME,                   "name") \
        _(ZEND_STR_ARGV,                   "argv") \
        _(ZEND_STR_ARGC,                   "argc") \
+       _(ZEND_STR_ARRAY_CAPITALIZED,      "Array") \
 
 
 typedef enum _zend_known_string_id {
index b4d41dfa59120c18d910af53c45cd8dd0b5bf4fc..f31b05991dfe5ab80a2ea1f1a13ce092c07505a4 100644 (file)
@@ -1649,6 +1649,11 @@ ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
                        ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+                       FREE_OP1();
+                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -5909,6 +5914,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
                        varname = ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+                       FREE_OP1();
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -7923,7 +7932,9 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
                                }
                                zval_ptr_dtor(&tmp);
                        }
-                       zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       if (!EG(exception)) {
+                               zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       }
                        ZVAL_NULL(EX_VAR(opline->result.var));
                } while (0);
        }
index b967d281dc546c6591ee5c99fdd77e8b6378e8de..178f7b335ac69cbabe2b8e844b3b65dfe1ec4529 100644 (file)
@@ -4184,7 +4184,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST
                                }
                                zval_ptr_dtor(&tmp);
                        }
-                       zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       if (!EG(exception)) {
+                               zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       }
                        ZVAL_NULL(EX_VAR(opline->result.var));
                } while (0);
        }
@@ -8694,6 +8696,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
                        ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+
+                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -9205,6 +9212,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA
                        varname = ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -12959,7 +12970,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN
                                }
                                zval_ptr_dtor(&tmp);
                        }
-                       zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       if (!EG(exception)) {
+                               zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       }
                        ZVAL_NULL(EX_VAR(opline->result.var));
                } while (0);
        }
@@ -16093,6 +16106,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
                        ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+                       zval_ptr_dtor_nogc(free_op1);
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -16213,6 +16230,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H
                        varname = ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+                       zval_ptr_dtor_nogc(free_op1);
+                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -40041,7 +40063,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP
                                }
                                zval_ptr_dtor(&tmp);
                        }
-                       zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       if (!EG(exception)) {
+                               zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+                       }
                        ZVAL_NULL(EX_VAR(opline->result.var));
                } while (0);
        }
@@ -48775,6 +48799,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
                        ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -49597,6 +49625,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL
                        varname = ZVAL_UNDEFINED_OP1();
                }
                name = zval_get_tmp_string(varname, &tmp_name);
+               if (UNEXPECTED(EG(exception))) {
+
+                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                       HANDLE_EXCEPTION();
+               }
        }
 
        target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
index f7db8a26d78fe1760e3f3521bf67664908f562e7..3e8fb419d810bb7dbdae581afcd5b49133255758 100644 (file)
@@ -2043,6 +2043,9 @@ static int date_interval_has_property(zval *object, zval *member, int type, void
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return 0;
+               }
        }
 
        obj = Z_PHPINTERVAL_P(object);
@@ -4167,6 +4170,9 @@ static zval *date_interval_read_property(zval *object, zval *member, int type, v
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return &EG(uninitialized_zval);
+               }
        }
 
        obj = Z_PHPINTERVAL_P(object);
@@ -4235,6 +4241,9 @@ static zval *date_interval_write_property(zval *object, zval *member, zval *valu
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return value;
+               }
        }
 
        obj = Z_PHPINTERVAL_P(object);
@@ -4286,6 +4295,9 @@ static zval *date_interval_get_property_ptr_ptr(zval *object, zval *member, int
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return NULL;
+               }
        }
 
        if(zend_binary_strcmp("y", sizeof("y") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
index ede12f0bd673d155c4cde697bfc8b181388134d9..952993582b413bd8be4c4dfb1e88d1724ce2a8a7 100644 (file)
@@ -672,6 +672,12 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                keylen += Z_STRLEN(args[i]);
        }
 
+       /* Exception during string conversion */
+       if (EG(exception)) {
+               FREENOW;
+               return;
+       }
+
        if (persistent) {
                zend_resource *le;
 
index f59b46799f630138e8060c657fde6caf4c7e4107..025570851733ef37f794ff6531217ec7b89dab2e 100644 (file)
@@ -160,12 +160,15 @@ int dom_attr_value_write(dom_object *obj, zval *newval)
                return FAILURE;
        }
 
+       str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
+
        if (attrp->children) {
                node_list_unlink(attrp->children);
        }
 
-       str = zval_get_string(newval);
-
        xmlNodeSetContentLen((xmlNodePtr) attrp, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
 
        zend_string_release_ex(str, 0);
index f47324049894b51f99b53c09a97baf238909bb4e..76763706774e932137c935d76d76cce810f40af0 100644 (file)
@@ -105,6 +105,9 @@ int dom_characterdata_data_write(dom_object *obj, zval *newval)
        }
 
        str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
 
        xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
 
index 95b077b6483a1a314460703b4dd3c98993f6bae7..235323e1d7bd32d137675b71e9a0fba11460d3d9 100644 (file)
@@ -338,6 +338,9 @@ int dom_document_encoding_write(dom_object *obj, zval *newval)
        }
 
        str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
 
        handler = xmlFindCharEncodingHandler(Z_STRVAL_P(newval));
 
@@ -431,12 +434,15 @@ int dom_document_version_write(dom_object *obj, zval *newval)
                return FAILURE;
        }
 
+       str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
+
        if (docp->version != NULL) {
                xmlFree((xmlChar *) docp->version );
        }
 
-       str = zval_get_string(newval);
-
        docp->version = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
 
        zend_string_release_ex(str, 0);
@@ -659,12 +665,15 @@ int dom_document_document_uri_write(dom_object *obj, zval *newval)
                return FAILURE;
        }
 
+       str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
+
        if (docp->URL != NULL) {
                xmlFree((xmlChar *) docp->URL);
        }
 
-       str = zval_get_string(newval);
-
        docp->URL = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
 
        zend_string_release_ex(str, 0);
index 03e61efa674a3d70f927dfa72e43a61f915439f6..44e6f58b30a488060a5f17f36c42b448bea98074 100644 (file)
@@ -323,12 +323,18 @@ int dom_node_node_value_read(dom_object *obj, zval *retval)
 int dom_node_node_value_write(dom_object *obj, zval *newval)
 {
        xmlNode *nodep = dom_object_get_node(obj);
+       zend_string *str;
 
        if (nodep == NULL) {
                php_dom_throw_error(INVALID_STATE_ERR, 0);
                return FAILURE;
        }
 
+       str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
+
        /* Access to Element node is implemented as a convenience method */
        switch (nodep->type) {
                case XML_ELEMENT_NODE:
@@ -342,16 +348,13 @@ int dom_node_node_value_write(dom_object *obj, zval *newval)
                case XML_COMMENT_NODE:
                case XML_CDATA_SECTION_NODE:
                case XML_PI_NODE:
-                       {
-                               zend_string *str = zval_get_string(newval);
-                               xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
-                               zend_string_release_ex(str, 0);
-                               break;
-                       }
+                       xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
+                       break;
                default:
                        break;
        }
 
+       zend_string_release_ex(str, 0);
        return SUCCESS;
 }
 
@@ -722,6 +725,10 @@ int dom_node_prefix_write(dom_object *obj, zval *newval)
                                }
                        }
                        str = zval_get_string(newval);
+                       if (EG(exception)) {
+                               return FAILURE;
+                       }
+
                        prefix = ZSTR_VAL(str);
                        if (nsnode && nodep->ns != NULL && !xmlStrEqual(nodep->ns->prefix, (xmlChar *)prefix)) {
                                strURI = (char *) nodep->ns->href;
@@ -854,6 +861,11 @@ int dom_node_text_content_write(dom_object *obj, zval *newval)
                return FAILURE;
        }
 
+       str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
+
        if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
                if (nodep->children) {
                        node_list_unlink(nodep->children);
@@ -862,7 +874,6 @@ int dom_node_text_content_write(dom_object *obj, zval *newval)
                }
        }
 
-       str = zval_get_string(newval);
        /* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
        xmlNodeSetContent(nodep, (xmlChar *) "");
        xmlNodeAddContent(nodep, (xmlChar *) ZSTR_VAL(str));
index 0487abc373d0af1a2ba2fc7b136dd0ac53f33a0b..103bfd74f039acb38b554697bfa475ab768ddfe4 100644 (file)
@@ -139,6 +139,9 @@ int dom_processinginstruction_data_write(dom_object *obj, zval *newval)
        }
 
        str = zval_get_string(newval);
+       if (EG(exception)) {
+               return FAILURE;
+       }
 
        xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
 
diff --git a/ext/dom/tests/toString_exceptions.phpt b/ext/dom/tests/toString_exceptions.phpt
new file mode 100644 (file)
index 0000000..e59532d
--- /dev/null
@@ -0,0 +1,56 @@
+--TEST--
+Handling of exceptions during __toString
+--FILE--
+<?php
+
+class BadStr {
+    public function __toString() {
+        throw new Exception("Exception");
+    }
+}
+
+$badStr = new BadStr;
+
+$doc = new DOMDocument();
+$doc->loadXML(
+    '<root xmlns:ns="foo"><node attr="foo" /><node>Text</node><ns:node/><?pi foobar?></root>');
+
+try { $doc->encoding = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+try { $doc->version = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+try { $doc->documentURI = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+$root = $doc->childNodes[0];
+
+$node = $root->childNodes[0];
+$attrs = $node->attributes;
+$attr = $attrs[0];
+try { $attr->value = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+try { $attr->nodeValue = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+
+$node2 = $root->childNodes[1];
+try { $node2->nodeValue = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+try { $node2->textContent = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+$data = $node2->childNodes[0];
+try { $data->data = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+
+$node3 = $root->childNodes[2];
+try { $node3->prefix = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+
+$pi = $root->childNodes[3];
+try { $pi->data = $badStr; } catch (Exception $e) { echo "Exception\n"; }
+
+echo $doc->saveXML();
+
+?>
+--EXPECT--
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+Exception
+<?xml version="1.0"?>
+<root xmlns:ns="foo"><node attr="foo"/><node>Text</node><ns:node/><?pi foobar?></root>
index 1fd42fe09623a1e881026bb86bfc534d0931a3c5..0ec5b1a1b820df5ba5974a786ffb794d109b9ca1 100644 (file)
@@ -4419,7 +4419,9 @@ PHP_FUNCTION(exif_read_data)
 
                ret = exif_read_from_stream(&ImageInfo, p_stream, read_thumbnail, read_all);
        } else {
-               convert_to_string(stream);
+               if (!try_convert_to_string(stream)) {
+                       return;
+               }
 
                if (!Z_STRLEN_P(stream)) {
                        exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_WARNING, "Filename cannot be empty");
@@ -4589,7 +4591,9 @@ PHP_FUNCTION(exif_thumbnail)
 
                ret = exif_read_from_stream(&ImageInfo, p_stream, 1, 0);
        } else {
-               convert_to_string(stream);
+               if (!try_convert_to_string(stream)) {
+                       return;
+               }
 
                if (!Z_STRLEN_P(stream)) {
                        exif_error_docref(NULL EXIFERR_CC, &ImageInfo, E_WARNING, "Filename cannot be empty");
index 786589d263b941156bab09922acadbab42659a27..9aa3953918d46119bf7a0f7e8ba3152c2acd1951 100644 (file)
@@ -2298,7 +2298,10 @@ PHP_FUNCTION(imagecreatefromstring)
                return;
        }
 
-       convert_to_string_ex(data);
+       if (!try_convert_to_string(data)) {
+               return;
+       }
+
        if (Z_STRLEN_P(data) < sizeof(sig)) {
                php_error_docref(NULL, E_WARNING, "Empty string or invalid image");
                RETURN_FALSE;
index bb40b6a215c481fdc4891d2ddfc21f30de8a6f15..688e3a25527a00ac24cc29639710929a208b54ac 100644 (file)
@@ -2243,7 +2243,7 @@ PHP_FUNCTION(iconv_mime_encode)
        if (pref != NULL) {
                zval *pzval;
 
-               if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "scheme", sizeof("scheme") - 1)) != NULL) {
+               if ((pzval = zend_hash_str_find_deref(Z_ARRVAL_P(pref), "scheme", sizeof("scheme") - 1)) != NULL) {
                        if (Z_TYPE_P(pzval) == IS_STRING && Z_STRLEN_P(pzval) > 0) {
                                switch (Z_STRVAL_P(pzval)[0]) {
                                        case 'B': case 'b':
@@ -2257,7 +2257,7 @@ PHP_FUNCTION(iconv_mime_encode)
                        }
                }
 
-               if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "input-charset", sizeof("input-charset") - 1)) != NULL && Z_TYPE_P(pzval) == IS_STRING) {
+               if ((pzval = zend_hash_str_find_deref(Z_ARRVAL_P(pref), "input-charset", sizeof("input-charset") - 1)) != NULL && Z_TYPE_P(pzval) == IS_STRING) {
                        if (Z_STRLEN_P(pzval) >= ICONV_CSNMAXLEN) {
                                php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
                                RETURN_FALSE;
@@ -2269,7 +2269,7 @@ PHP_FUNCTION(iconv_mime_encode)
                }
 
 
-               if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "output-charset", sizeof("output-charset") - 1)) != NULL && Z_TYPE_P(pzval) == IS_STRING) {
+               if ((pzval = zend_hash_str_find_deref(Z_ARRVAL_P(pref), "output-charset", sizeof("output-charset") - 1)) != NULL && Z_TYPE_P(pzval) == IS_STRING) {
                        if (Z_STRLEN_P(pzval) >= ICONV_CSNMAXLEN) {
                                php_error_docref(NULL, E_WARNING, "Charset parameter exceeds the maximum allowed length of %d characters", ICONV_CSNMAXLEN);
                                RETURN_FALSE;
@@ -2280,13 +2280,16 @@ PHP_FUNCTION(iconv_mime_encode)
                        }
                }
 
-               if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "line-length", sizeof("line-length") - 1)) != NULL) {
+               if ((pzval = zend_hash_str_find_deref(Z_ARRVAL_P(pref), "line-length", sizeof("line-length") - 1)) != NULL) {
                        line_len = zval_get_long(pzval);
                }
 
-               if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars") - 1)) != NULL) {
+               if ((pzval = zend_hash_str_find_deref(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars") - 1)) != NULL) {
                        if (Z_TYPE_P(pzval) != IS_STRING) {
                                tmp_str = zval_get_string_func(pzval);
+                               if (EG(exception)) {
+                                       return;
+                               }
                                lfchars = ZSTR_VAL(tmp_str);
                        } else {
                                lfchars = Z_STRVAL_P(pzval);
index 3cee4e023edce2eb4166c75b3435d21f4a4c8782..b5f12f6eee0f73027b5e4ba1314a06bc8320a98b 100644 (file)
@@ -2060,7 +2060,9 @@ PHP_FUNCTION(imap_delete)
                RETURN_FALSE;
        }
 
-       convert_to_string_ex(sequence);
+       if (!try_convert_to_string(sequence)) {
+               return;
+       }
 
        mail_setflag_full(imap_le_struct->imap_stream, Z_STRVAL_P(sequence), "\\DELETED", (argc == 3 ? flags : NIL));
        RETVAL_TRUE;
@@ -2084,7 +2086,9 @@ PHP_FUNCTION(imap_undelete)
                RETURN_FALSE;
        }
 
-       convert_to_string_ex(sequence);
+       if (!try_convert_to_string(sequence)) {
+               return;
+       }
 
        mail_clearflag_full(imap_le_struct->imap_stream, Z_STRVAL_P(sequence), "\\DELETED", (argc == 3 ? flags : NIL));
        RETVAL_TRUE;
@@ -2503,7 +2507,9 @@ PHP_FUNCTION(imap_savebody)
                break;
 
                default:
-                       convert_to_string_ex(out);
+                       if (!try_convert_to_string(out)) {
+                               return;
+                       }
                        writer = php_stream_open_wrapper(Z_STRVAL_P(out), "wb", REPORT_ERRORS, NULL);
                break;
        }
index c2429fb592c9dc4f2862105e6f655ab052c24d59..90e148bca03d1bfc34ce68d48378ddbc80415193 100644 (file)
@@ -142,7 +142,9 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object)
                }
                dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_P(format);
        } else {
-               convert_to_string_ex(format);
+               if (!try_convert_to_string(format)) {
+                       return;
+               }
                if (Z_STRLEN_P(format) == 0) {
                        intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
                                        "datefmt_format_object: the format is empty", 0);
index aabb0f3f55393923debfa057682c249b213aee14..695cc7d3ea1e5cffdea33a4965eba2e659be7051 100644 (file)
@@ -179,7 +179,10 @@ U_CFUNC TimeZone *timezone_process_timezone_argument(zval *zv_timezone,
                UnicodeString   id,
                                                gottenId;
                UErrorCode              status = U_ZERO_ERROR; /* outside_error may be NULL */
-               convert_to_string_ex(zv_timezone);
+               if (!try_convert_to_string(zv_timezone)) {
+                       zval_ptr_dtor_str(&local_zv_tz);
+                       return NULL;
+               }
                if (intl_stringFromChar(id, Z_STRVAL_P(zv_timezone), Z_STRLEN_P(zv_timezone),
                                &status) == FAILURE) {
                        spprintf(&message, 0, "%s: Time zone identifier given is not a "
index 3f91db3130da247671eda95ad91de55ab0315a59..6e1d22324b1153213b76a71667590716244d2989 100644 (file)
@@ -177,7 +177,9 @@ double_offset:
        } else if (Z_TYPE_P(arg) == IS_OBJECT || Z_TYPE_P(arg) == IS_STRING) {
                zend_long lval;
                double dval;
-               convert_to_string_ex(arg);
+               if (!try_convert_to_string(arg)) {
+                       return;
+               }
                switch (is_numeric_string(Z_STRVAL_P(arg), Z_STRLEN_P(arg), &lval, &dval, 0)) {
                case IS_DOUBLE:
                        zval_ptr_dtor(arg);
index a662dcee7dce00c2c59bf9e3bc79653989c35557..a619ed4309ece7b63b04075bdb2a5b50c9651a05 100644 (file)
@@ -189,7 +189,7 @@ err:
 }
 /* }}} */
 
-#define TRANSLITERATOR_PROPERTY_HANDLER_PROLOG  \
+#define TRANSLITERATOR_PROPERTY_HANDLER_PROLOG(return_fail) \
        zval tmp_member;                                                        \
        if( Z_TYPE_P( member ) != IS_STRING )           \
        {                                                                                       \
@@ -197,6 +197,7 @@ err:
                        zval_get_string_func(member));          \
                member = &tmp_member;                                   \
                cache_slot = NULL;                                              \
+               if (EG(exception)) { return_fail; }             \
     }
 
 #define TRANSLITERATOR_PROPERTY_HANDLER_EPILOG \
@@ -210,7 +211,7 @@ static zval *Transliterator_get_property_ptr_ptr( zval *object, zval *member, in
 {
        zval *retval;
 
-       TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
+       TRANSLITERATOR_PROPERTY_HANDLER_PROLOG(return NULL);
 
        if(zend_binary_strcmp( "id", sizeof( "id" ) - 1,
                Z_STRVAL_P( member ), Z_STRLEN_P( member ) ) == 0 )
@@ -233,7 +234,7 @@ static zval *Transliterator_read_property( zval *object, zval *member, int type,
 {
        zval *retval;
 
-       TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
+       TRANSLITERATOR_PROPERTY_HANDLER_PROLOG(return &EG(uninitialized_zval));
 
        if( ( type != BP_VAR_R && type != BP_VAR_IS ) &&
                ( zend_binary_strcmp( "id", sizeof( "id" ) - 1,
@@ -258,7 +259,7 @@ static zval *Transliterator_read_property( zval *object, zval *member, int type,
 static zval *Transliterator_write_property( zval *object, zval *member, zval *value, void **cache_slot )
 {
        zend_class_entry *scope;
-       TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
+       TRANSLITERATOR_PROPERTY_HANDLER_PROLOG(return value);
 
        if (EG(fake_scope)) {
                scope = EG(fake_scope);
index 25d0b9a4dae21aac23587251c1b4c914a76460e8..50dd344671a52c867b7eacbc54c4dcbd42755f25 100644 (file)
@@ -330,9 +330,8 @@ PHP_FUNCTION( transliterator_transliterate )
                else
                { /* not a transliterator object as first argument */
                        int res;
-                       if(Z_TYPE_P( arg1 ) != IS_STRING )
-                       {
-                               convert_to_string( arg1 );
+                       if( !try_convert_to_string( arg1 ) ) {
+                               return;
                        }
                        object = &tmp_object;
                        res = create_transliterator( Z_STRVAL_P( arg1 ), Z_STRLEN_P( arg1 ),
index 7471065494cce906373dac92c97ab0902318371a..15ef274ee4e49fd4ee0be327a28570d56b0be05c 100644 (file)
@@ -662,8 +662,9 @@ is_string:
                        }
                } else if (Z_TYPE(retval) != IS_NULL) {
                        /* retval not string nor resource nor null; convert to string */
-                       convert_to_string(&retval);
-                       goto is_string;
+                       if (try_convert_to_string(&retval)) {
+                               goto is_string;
+                       }
                } /* else is null; don't try anything */
        }
 
index 69d5fa91017c130016eb5c071dd282614c00232e..e3611562e58b0e2a2d47b3374ca4b594d0efe216 100644 (file)
@@ -826,8 +826,13 @@ php_mb_parse_encoding_array(zval *array, const mbfl_encoding ***return_list, siz
                bauto = 0;
                n = 0;
                ZEND_HASH_FOREACH_VAL(target_hash, hash_entry) {
-                       convert_to_string_ex(hash_entry);
-                       if (strcasecmp(Z_STRVAL_P(hash_entry), "auto") == 0) {
+                       zend_string *encoding_str = zval_get_string(hash_entry);
+                       if (EG(exception)) {
+                               ret = FAILURE;
+                               break;
+                       }
+
+                       if (strcasecmp(ZSTR_VAL(encoding_str), "auto") == 0) {
                                if (!bauto) {
                                        const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
                                        const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
@@ -840,7 +845,7 @@ php_mb_parse_encoding_array(zval *array, const mbfl_encoding ***return_list, siz
                                        }
                                }
                        } else {
-                               const mbfl_encoding *encoding = mbfl_name2encoding(Z_STRVAL_P(hash_entry));
+                               const mbfl_encoding *encoding = mbfl_name2encoding(ZSTR_VAL(encoding_str));
                                if (encoding) {
                                        *entry++ = encoding;
                                        n++;
@@ -849,6 +854,7 @@ php_mb_parse_encoding_array(zval *array, const mbfl_encoding ***return_list, siz
                                }
                        }
                        i--;
+                       zend_string_release(encoding_str);
                } ZEND_HASH_FOREACH_END();
                if (n > 0) {
                        if (return_list) {
@@ -2000,7 +2006,9 @@ PHP_FUNCTION(mb_detect_order)
                                }
                                break;
                        default:
-                               convert_to_string_ex(arg1);
+                               if (!try_convert_to_string(arg1)) {
+                                       return;
+                               }
                                if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(arg1), Z_STRLEN_P(arg1), &list, &size, 0)) {
                                        if (list) {
                                                efree(list);
@@ -3328,7 +3336,9 @@ PHP_FUNCTION(mb_convert_encoding)
        }
 
        if (Z_TYPE_P(input) != IS_STRING && Z_TYPE_P(input) != IS_ARRAY) {
-               convert_to_string(input);
+               if (!try_convert_to_string(input)) {
+                       return;
+               }
        }
 
        if (arg_old) {
@@ -3338,8 +3348,13 @@ PHP_FUNCTION(mb_convert_encoding)
                                _from_encodings = NULL;
 
                                ZEND_HASH_FOREACH_VAL(target_hash, hash_entry) {
-
-                                       convert_to_string_ex(hash_entry);
+                                       zend_string *encoding_str = zval_get_string(hash_entry);
+                                       if (EG(exception)) {
+                                               if (_from_encodings) {
+                                                       efree(_from_encodings);
+                                               }
+                                               return;
+                                       }
 
                                        if ( _from_encodings) {
                                                l = strlen(_from_encodings);
@@ -3350,6 +3365,7 @@ PHP_FUNCTION(mb_convert_encoding)
                                        } else {
                                                _from_encodings = estrdup(Z_STRVAL_P(hash_entry));
                                        }
+                                       zend_string_release(encoding_str);
                                } ZEND_HASH_FOREACH_END();
 
                                if (_from_encodings != NULL && !strlen(_from_encodings)) {
@@ -3359,7 +3375,10 @@ PHP_FUNCTION(mb_convert_encoding)
                                s_free = _from_encodings;
                                break;
                        default:
-                               convert_to_string(arg_old);
+                               if (!try_convert_to_string(arg_old)) {
+                                       return;
+                               }
+
                                _from_encodings = Z_STRVAL_P(arg_old);
                                break;
                        }
@@ -3535,7 +3554,9 @@ PHP_FUNCTION(mb_detect_encoding)
                        }
                        break;
                default:
-                       convert_to_string(encoding_list);
+                       if (!try_convert_to_string(encoding_list)) {
+                               return;
+                       }
                        if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &list, &size, 0)) {
                                if (list) {
                                        efree(list);
@@ -3944,7 +3965,9 @@ PHP_FUNCTION(mb_convert_variables)
                        php_mb_parse_encoding_array(zfrom_enc, &elist, &elistsz, 0);
                        break;
                default:
-                       convert_to_string_ex(zfrom_enc);
+                       if (!try_convert_to_string(zfrom_enc)) {
+                               return;
+                       }
                        php_mb_parse_encoding_list(Z_STRVAL_P(zfrom_enc), Z_STRLEN_P(zfrom_enc), &elist, &elistsz, 0);
                        break;
        }
index 83cd25d89da592b03530ca77f3650e204ce46e2f..9fac8233ba1e5d5253d386643204a33d05c4b4a9 100644 (file)
@@ -924,7 +924,9 @@ static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
                if (Z_TYPE_P(arg_pattern) == IS_DOUBLE) {
                        convert_to_long_ex(arg_pattern);        /* get rid of decimal places */
                }
-               convert_to_string_ex(arg_pattern);
+               if (!try_convert_to_string(arg_pattern)) {
+                       return;
+               }
                /* don't bother doing an extended regex with just a number */
        }
 
index 394a8385124f297d4fadf2f041f9c40dbdc1972a..9964ea0be49c97aa189df91a2f973ca4a7890b94 100644 (file)
@@ -309,6 +309,9 @@ zval *mysqli_read_property(zval *object, zval *member, int type, void **cache_sl
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return &EG(uninitialized_zval);
+               }
        }
 
        if (obj->prop_handler != NULL) {
@@ -342,6 +345,9 @@ zval *mysqli_write_property(zval *object, zval *member, zval *value, void **cach
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return value;
+               }
        }
 
        obj = Z_MYSQLI_P(object);
index 1a7303c987d4d74f994b894bd24a13c464c31af1..13d21e93124103ac62c8c18a28aa65078a6d893f 100644 (file)
@@ -899,7 +899,10 @@ PHP_FUNCTION(mysqli_stmt_execute)
                        if (!(stmt->param.is_null[i] = (Z_ISNULL_P(param)))) {
                                switch (stmt->stmt->params[i].buffer_type) {
                                        case MYSQL_TYPE_VAR_STRING:
-                                               convert_to_string_ex(param);
+                                               if (!try_convert_to_string(param)) {
+                                                       return;
+                                               }
+
                                                stmt->stmt->params[i].buffer = Z_STRVAL_P(param);
                                                stmt->stmt->params[i].buffer_length = Z_STRLEN_P(param);
                                                break;
@@ -1781,7 +1784,9 @@ PHP_FUNCTION(mysqli_options)
        if (expected_type != Z_TYPE_P(mysql_value)) {
                switch (expected_type) {
                        case IS_STRING:
-                               convert_to_string_ex(mysql_value);
+                               if (!try_convert_to_string(mysql_value)) {
+                                       return;
+                               }
                                break;
                        case IS_LONG:
                                convert_to_long_ex(mysql_value);
index 641c7ee7834ff875bc5217d49eecb52b155ea7d4..7da46a90f836b3e87c39aa1f8d5ae6410169cdac 100644 (file)
@@ -777,7 +777,10 @@ use_string:
                                        }
                                        the_var = &((*copies_param)[i]);
                                }
-                               convert_to_string_ex(the_var);
+
+                               if (!try_convert_to_string(the_var)) {
+                                       goto end;
+                               }
                                *data_size += Z_STRLEN_P(the_var);
                                break;
                }
index 4face29e4a6d732eaa9b9da264d44e4cf9d42100..91f6223373c38b3ab4af2ec63ba3430f1d27d0af 100644 (file)
@@ -1189,7 +1189,9 @@ int php_oci_bind_by_name(php_oci_statement *statement, char *name, size_t name_l
                                return 1;
                        }
                        if (Z_TYPE_P(param) != IS_NULL) {
-                               convert_to_string(param);
+                               if (!try_convert_to_string(param)) {
+                                       return 1;
+                               }
                        }
                        if ((maxlength == -1) || (maxlength == 0)) {
                                if (type == SQLT_LNG) {
@@ -1390,8 +1392,10 @@ sb4 php_oci_bind_in_callback(
                *alenp = -1;
                *indpp = (dvoid *)&phpbind->indicator;
        } else  if ((phpbind->descriptor == 0) && (phpbind->statement == 0)) {
-               /* "normal string bind */
-               convert_to_string(val);
+               /* "normal" string bind */
+               if (!try_convert_to_string(val)) {
+                       return OCI_ERROR;
+               }
 
                *bufpp = Z_STRVAL_P(val);
                *alenp = (ub4) Z_STRLEN_P(val);
@@ -1483,7 +1487,6 @@ sb4 php_oci_bind_out_callback(
                *indpp = &phpbind->indicator;
                retval = OCI_CONTINUE;
        } else {
-               convert_to_string(val);
                zval_ptr_dtor(val);
 
                {
@@ -1741,7 +1744,9 @@ php_oci_bind *php_oci_bind_array_helper_string(zval *var, zend_long max_table_le
        if (maxlength == -1) {
                zend_hash_internal_pointer_reset(hash);
                while ((entry = zend_hash_get_current_data(hash)) != NULL) {
-                       convert_to_string_ex(entry);
+                       if (!try_convert_to_string(entry)) {
+                               return NULL;
+                       }
 
                        if (maxlength == -1 || Z_STRLEN_P(entry) > (size_t) maxlength) {
                                maxlength = Z_STRLEN_P(entry) + 1;
@@ -1767,7 +1772,14 @@ php_oci_bind *php_oci_bind_array_helper_string(zval *var, zend_long max_table_le
 
        for (i = 0; i < bind->array.current_length; i++) {
                if ((entry = zend_hash_get_current_data(hash)) != NULL) {
-                       convert_to_string_ex(entry);
+                       if (!try_convert_to_string(entry)) {
+                               efree(bind->array.elements);
+                               efree(bind->array.element_lengths);
+                               efree(bind->array.indicators);
+                               efree(bind);
+                               return NULL;
+                       }
+
                        bind->array.element_lengths[i] = (ub2) Z_STRLEN_P(entry);
                        if (Z_STRLEN_P(entry) == 0) {
                                bind->array.indicators[i] = -1;
@@ -1782,8 +1794,14 @@ php_oci_bind *php_oci_bind_array_helper_string(zval *var, zend_long max_table_le
        for (i = 0; i < max_table_length; i++) {
                if ((i < bind->array.current_length) && (entry = zend_hash_get_current_data(hash)) != NULL) {
                        int element_length;
+                       if (!try_convert_to_string(entry)) {
+                               efree(bind->array.elements);
+                               efree(bind->array.element_lengths);
+                               efree(bind->array.indicators);
+                               efree(bind);
+                               return NULL;
+                       }
 
-                       convert_to_string_ex(entry);
                        element_length = ((size_t) maxlength > Z_STRLEN_P(entry)) ? (int) Z_STRLEN_P(entry) : (int) maxlength;
 
                        memcpy((text *)bind->array.elements + i*maxlength, Z_STRVAL_P(entry), element_length);
@@ -1912,9 +1930,16 @@ php_oci_bind *php_oci_bind_array_helper_date(zval *var, zend_long max_table_leng
                        bind->array.element_lengths[i] = sizeof(OCIDate);
                }
                if ((i < bind->array.current_length) && (entry = zend_hash_get_current_data(hash)) != NULL) {
+                       zend_string *entry_str = zval_get_string(entry);
+                       if (EG(exception)) {
+                               efree(bind->array.element_lengths);
+                               efree(bind->array.elements);
+                               efree(bind);
+                               return NULL;
+                       }
 
-                       convert_to_string_ex(entry);
-                       PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)Z_STRVAL_P(entry), (ub4) Z_STRLEN_P(entry), NULL, 0, NULL, 0, &oci_date));
+                       PHP_OCI_CALL_RETURN(errstatus, OCIDateFromText, (connection->err, (CONST text *)ZSTR_VAL(entry_str), (ub4) ZSTR_LEN(entry_str), NULL, 0, NULL, 0, &oci_date));
+                       zend_string_release(entry_str);
 
                        if (errstatus != OCI_SUCCESS) {
                                /* failed to convert string to date */
index 37257c3e12c6a4d4b81921e466253e3374f0c68d..6bd24781b44ea2f9b17c16a844ba74186151cb63 100644 (file)
@@ -1343,9 +1343,7 @@ PHP_FUNCTION(odbc_execute)
                        }
 
                        otype = Z_TYPE_P(tmp);
-                       convert_to_string_ex(tmp);
-                       if (Z_TYPE_P(tmp) != IS_STRING) {
-                               php_error_docref(NULL, E_WARNING,"Error converting parameter");
+                       if (!try_convert_to_string(tmp)) {
                                SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
                                for (i = 0; i < result->numparams; i++) {
                                        if (params[i].fp != -1) {
index 8cf294b361177c686abc1b3652627eae668f453d..7f287c88234dc8607987ef813d8fd858b2b64be6 100644 (file)
@@ -1725,7 +1725,9 @@ static X509 * php_openssl_x509_from_zval(zval * val, int makeresource, zend_reso
        }
 
        /* force it to be a string and check if it refers to a file */
-       convert_to_string_ex(val);
+       if (!try_convert_to_string(val)) {
+               return NULL;
+       }
 
        if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
 
@@ -2671,32 +2673,37 @@ static X509_STORE *php_openssl_setup_verify(zval *calist)
 
        if (calist && (Z_TYPE_P(calist) == IS_ARRAY)) {
                ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(calist), item) {
-                       convert_to_string_ex(item);
+                       zend_string *str = zval_get_string(item);
+                       if (EG(exception)) {
+                               return NULL;
+                       }
 
-                       if (VCWD_STAT(Z_STRVAL_P(item), &sb) == -1) {
-                               php_error_docref(NULL, E_WARNING, "unable to stat %s", Z_STRVAL_P(item));
+                       if (VCWD_STAT(ZSTR_VAL(str), &sb) == -1) {
+                               php_error_docref(NULL, E_WARNING, "unable to stat %s", ZSTR_VAL(str));
+                               zend_string_release(str);
                                continue;
                        }
 
                        if ((sb.st_mode & S_IFREG) == S_IFREG) {
                                file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
-                               if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, Z_STRVAL_P(item), X509_FILETYPE_PEM)) {
+                               if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, ZSTR_VAL(str), X509_FILETYPE_PEM)) {
                                        php_openssl_store_errors();
-                                       php_error_docref(NULL, E_WARNING, "error loading file %s", Z_STRVAL_P(item));
+                                       php_error_docref(NULL, E_WARNING, "error loading file %s", ZSTR_VAL(str));
                                } else {
                                        nfiles++;
                                }
                                file_lookup = NULL;
                        } else {
                                dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
-                               if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, Z_STRVAL_P(item), X509_FILETYPE_PEM)) {
+                               if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, ZSTR_VAL(str), X509_FILETYPE_PEM)) {
                                        php_openssl_store_errors();
-                                       php_error_docref(NULL, E_WARNING, "error loading directory %s", Z_STRVAL_P(item));
+                                       php_error_docref(NULL, E_WARNING, "error loading directory %s", ZSTR_VAL(str));
                                } else {
                                        ndirs++;
                                }
                                dir_lookup = NULL;
                        }
+                       zend_string_release(str);
                } ZEND_HASH_FOREACH_END();
        }
        if (nfiles == 0) {
@@ -3145,23 +3152,25 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
                /* apply values from the dn hash */
                ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(dn), strindex, item) {
                        if (strindex) {
-                               int nid;
-
-                               convert_to_string_ex(item);
-
-                               nid = OBJ_txt2nid(ZSTR_VAL(strindex));
+                               int nid = OBJ_txt2nid(ZSTR_VAL(strindex));
                                if (nid != NID_undef) {
+                                       zend_string *str_item = zval_get_string(item);
+                                       if (EG(exception)) {
+                                               return FAILURE;
+                                       }
                                        if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8,
-                                                               (unsigned char*)Z_STRVAL_P(item), -1, -1, 0))
+                                                               (unsigned char*)ZSTR_VAL(str_item), -1, -1, 0))
                                        {
                                                php_openssl_store_errors();
                                                php_error_docref(NULL, E_WARNING,
                                                        "dn: add_entry_by_NID %d -> %s (failed; check error"
                                                        " queue and value of string_mask OpenSSL option "
                                                        "if illegal characters are reported)",
-                                                       nid, Z_STRVAL_P(item));
+                                                       nid, ZSTR_VAL(str_item));
+                                               zend_string_release(str_item);
                                                return FAILURE;
                                        }
+                                       zend_string_release(str_item);
                                } else {
                                        php_error_docref(NULL, E_WARNING, "dn: %s is not a recognized name", ZSTR_VAL(strindex));
                                }
@@ -3226,15 +3235,19 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
                                        continue;
                                }
 
-                               convert_to_string_ex(item);
-
                                nid = OBJ_txt2nid(ZSTR_VAL(strindex));
                                if (nid != NID_undef) {
-                                       if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (unsigned char*)Z_STRVAL_P(item), -1, -1, 0)) {
+                                       zend_string *str_item = zval_get_string(item);
+                                       if (EG(exception)) {
+                                               return FAILURE;
+                                       }
+                                       if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (unsigned char*)ZSTR_VAL(str_item), -1, -1, 0)) {
                                                php_openssl_store_errors();
-                                               php_error_docref(NULL, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_P(item));
+                                               php_error_docref(NULL, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, ZSTR_VAL(str_item));
+                                               zend_string_release(str_item);
                                                return FAILURE;
                                        }
+                                       zend_string_release(str_item);
                                } else {
                                        php_error_docref(NULL, E_WARNING, "dn: %s is not a recognized name", ZSTR_VAL(strindex));
                                }
@@ -3803,7 +3816,10 @@ static EVP_PKEY * php_openssl_evp_from_zval(
                        passphrase_len = Z_STRLEN_P(zphrase);
                } else {
                        ZVAL_COPY(&tmp, zphrase);
-                       convert_to_string(&tmp);
+                       if (!try_convert_to_string(&tmp)) {
+                               return NULL;
+                       }
+
                        passphrase = Z_STRVAL(tmp);
                        passphrase_len = Z_STRLEN(tmp);
                }
@@ -3864,7 +3880,9 @@ static EVP_PKEY * php_openssl_evp_from_zval(
                if (!(Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_OBJECT)) {
                        TMP_CLEAN;
                }
-               convert_to_string_ex(val);
+               if (!try_convert_to_string(val)) {
+                       TMP_CLEAN;
+               }
 
                if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
                        filename = Z_STRVAL_P(val) + (sizeof("file://") - 1);
@@ -5351,13 +5369,16 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)
        /* tack on extra headers */
        if (zheaders) {
                ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, zcertval) {
-                       convert_to_string_ex(zcertval);
-
+                       zend_string *str = zval_get_string(zcertval);
+                       if (EG(exception)) {
+                               goto clean_exit;
+                       }
                        if (strindex) {
-                               BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), Z_STRVAL_P(zcertval));
+                               BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
                        } else {
-                               BIO_printf(outfile, "%s\n", Z_STRVAL_P(zcertval));
+                               BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
                        }
+                       zend_string_release(str);
                } ZEND_HASH_FOREACH_END();
        }
 
@@ -5566,13 +5587,16 @@ PHP_FUNCTION(openssl_pkcs7_sign)
                int ret;
 
                ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheaders), strindex, hval) {
-                       convert_to_string_ex(hval);
-
+                       zend_string *str = zval_get_string(hval);
+                       if (EG(exception)) {
+                               goto clean_exit;
+                       }
                        if (strindex) {
-                               ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), Z_STRVAL_P(hval));
+                               ret = BIO_printf(outfile, "%s: %s\n", ZSTR_VAL(strindex), ZSTR_VAL(str));
                        } else {
-                               ret = BIO_printf(outfile, "%s\n", Z_STRVAL_P(hval));
+                               ret = BIO_printf(outfile, "%s\n", ZSTR_VAL(str));
                        }
+                       zend_string_release(str);
                        if (ret < 0) {
                                php_openssl_store_errors();
                        }
index fa25d93d62ec8787b76ee602d111022485f9ef3d..e6e345d5eaa975c98a3f410fdca57e4517785ece 100644 (file)
@@ -19,7 +19,11 @@ var_dump(openssl_x509_parse($t));
 var_dump(openssl_x509_parse(array()));
 var_dump(openssl_x509_parse());
 var_dump(openssl_x509_parse($cert));
-var_dump(openssl_x509_parse(new stdClass));
+try {
+    var_dump(openssl_x509_parse(new stdClass));
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 ?>
 --EXPECTF--
@@ -30,5 +34,4 @@ bool(false)
 Warning: openssl_x509_parse() expects at least 1 parameter, 0 given in %sbug38261.php on line %d
 NULL
 bool(false)
-
-Recoverable fatal error: Object of class stdClass could not be converted to string in %sbug38261.php on line %d 
+Object of class stdClass could not be converted to string
index f892c6854f80f28eea0e9dedf2c33806893bc3a0..63dabe8f32f674ea87d8d3d64aa3442b230f67e3 100644 (file)
@@ -15,7 +15,11 @@ $b = 1;
 $c = new stdclass;
 $d = new stdclass;
 
-var_dump(openssl_pkcs7_decrypt($a, $b, $c, $d));
+try {
+    var_dump(openssl_pkcs7_decrypt($a, $b, $c, $d));
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 var_dump($c);
 
 var_dump(openssl_pkcs7_decrypt($b, $b, $b, $b));
@@ -26,9 +30,7 @@ var_dump(openssl_pkcs7_decrypt($a, $b, 0, 0));
 echo "Done\n";
 ?>
 --EXPECT--
-string(57) "Object of class stdClass could not be converted to string"
-string(66) "openssl_pkcs7_decrypt(): unable to coerce parameter 3 to x509 cert"
-bool(false)
+Object of class stdClass could not be converted to string
 object(stdClass)#1 (0) {
 }
 string(66) "openssl_pkcs7_decrypt(): unable to coerce parameter 3 to x509 cert"
index d5276cd5b934437e4c64832f6c37c88097a2a87d..ad08e1f13a625e8281fec065ab259101f68786ec 100644 (file)
@@ -97,7 +97,9 @@
 #define GET_VER_OPT(name) \
        (PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", name)) != NULL)
 #define GET_VER_OPT_STRING(name, str) \
-       if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_P(val); }
+       if (GET_VER_OPT(name)) { \
+               if (try_convert_to_string(val)) str = Z_STRVAL_P(val); \
+       }
 #define GET_VER_OPT_LONG(name, num) \
        if (GET_VER_OPT(name)) { num = zval_get_long(val); }
 
@@ -1251,7 +1253,10 @@ static int php_openssl_set_server_dh_param(php_stream * stream, SSL_CTX *ctx) /*
                return SUCCESS;
        }
 
-       convert_to_string_ex(zdhpath);
+       if (!try_convert_to_string(zdhpath)) {
+               return FAILURE;
+       }
+
        bio = BIO_new_file(Z_STRVAL_P(zdhpath), PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
 
        if (bio == NULL) {
@@ -1295,7 +1300,10 @@ static int php_openssl_set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx) /
                curve_nid = NID_X9_62_prime256v1;
 #endif
        } else {
-               convert_to_string_ex(zvcurve);
+               if (!try_convert_to_string(zvcurve)) {
+                       return FAILURE;
+               }
+
                curve_nid = OBJ_sn2nid(Z_STRVAL_P(zvcurve));
                if (curve_nid == NID_undef) {
                        php_error_docref(NULL, E_WARNING, "invalid ecdh_curve specified");
@@ -1465,6 +1473,7 @@ static int php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstre
 
                if (Z_TYPE_P(current) == IS_ARRAY) {
                        zval *local_pk, *local_cert;
+                       zend_string *local_pk_str, *local_cert_str;
                        char resolved_cert_path_buff[MAXPATHLEN], resolved_pk_path_buff[MAXPATHLEN];
 
                        local_cert = zend_hash_str_find(Z_ARRVAL_P(current), "local_cert", sizeof("local_cert")-1);
@@ -1474,14 +1483,21 @@ static int php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstre
                                );
                                return FAILURE;
                        }
-                       convert_to_string_ex(local_cert);
-                       if (!VCWD_REALPATH(Z_STRVAL_P(local_cert), resolved_cert_path_buff)) {
+
+                       local_cert_str = zval_get_string(local_cert);
+                       if (EG(exception)) {
+                               return FAILURE;
+                       }
+                       if (!VCWD_REALPATH(ZSTR_VAL(local_cert_str), resolved_cert_path_buff)) {
                                php_error_docref(NULL, E_WARNING,
                                        "failed setting local cert chain file `%s'; file not found",
-                                       Z_STRVAL_P(local_cert)
+                                       ZSTR_VAL(local_cert_str)
                                );
+                               zend_string_release(local_cert_str);
                                return FAILURE;
                        }
+                       zend_string_release(local_cert_str);
+
                        local_pk = zend_hash_str_find(Z_ARRVAL_P(current), "local_pk", sizeof("local_pk")-1);
                        if (local_pk == NULL) {
                                php_error_docref(NULL, E_WARNING,
@@ -1489,14 +1505,20 @@ static int php_openssl_enable_server_sni(php_stream *stream, php_openssl_netstre
                                );
                                return FAILURE;
                        }
-                       convert_to_string_ex(local_pk);
-                       if (!VCWD_REALPATH(Z_STRVAL_P(local_pk), resolved_pk_path_buff)) {
+
+                       local_pk_str = zval_get_string(local_pk);
+                       if (EG(exception)) {
+                               return FAILURE;
+                       }
+                       if (!VCWD_REALPATH(ZSTR_VAL(local_pk_str), resolved_pk_path_buff)) {
                                php_error_docref(NULL, E_WARNING,
                                        "failed setting local private key file `%s'; file not found",
-                                       Z_STRVAL_P(local_pk)
+                                       ZSTR_VAL(local_pk_str)
                                );
+                               zend_string_release(local_pk_str);
                                return FAILURE;
                        }
+                       zend_string_release(local_pk_str);
 
                        ctx = php_openssl_create_sni_server_ctx(resolved_cert_path_buff, resolved_pk_path_buff);
 
index 63751d4b17b8c3a1be6ee3c1f0127a1a55d5bfac..300de1e7d48290038f6f05735f8b3b35bb34c57b 100644 (file)
@@ -967,6 +967,7 @@ PHP_FUNCTION(pcntl_exec)
 
        if (ZEND_NUM_ARGS() > 1) {
                /* Build argument list */
+               SEPARATE_ARRAY(args);
                args_hash = Z_ARRVAL_P(args);
                argc = zend_hash_num_elements(args_hash);
 
@@ -975,20 +976,25 @@ PHP_FUNCTION(pcntl_exec)
                current_arg = argv+1;
                ZEND_HASH_FOREACH_VAL(args_hash, element) {
                        if (argi >= argc) break;
-                       convert_to_string_ex(element);
+                       if (!try_convert_to_string(element)) {
+                               efree(argv);
+                               return;
+                       }
+
                        *current_arg = Z_STRVAL_P(element);
                        argi++;
                        current_arg++;
                } ZEND_HASH_FOREACH_END();
-               *(current_arg) = NULL;
+               *current_arg = NULL;
        } else {
                argv = emalloc(2 * sizeof(char *));
-               *argv = path;
-               *(argv+1) = NULL;
+               argv[0] = path;
+               argv[1] = NULL;
        }
 
        if ( ZEND_NUM_ARGS() == 3 ) {
                /* Build environment pair list */
+               SEPARATE_ARRAY(envs);
                envs_hash = Z_ARRVAL_P(envs);
                envc = zend_hash_num_elements(envs_hash);
 
@@ -1001,7 +1007,12 @@ PHP_FUNCTION(pcntl_exec)
                                zend_string_addref(key);
                        }
 
-                       convert_to_string_ex(element);
+                       if (!try_convert_to_string(element)) {
+                               zend_string_release(key);
+                               efree(argv);
+                               efree(envp);
+                               return;
+                       }
 
                        /* Length of element + equal sign + length of key + null */
                        pair_length = Z_STRLEN_P(element) + ZSTR_LEN(key) + 2;
index 05f8d9f81766bd33c4ab78d6e4b7dc0d814b9157..46794fe1d1a15dcfdaff57c9f14ba7b4e7211042 100644 (file)
@@ -1529,6 +1529,11 @@ PHPAPI zend_string *php_pcre_replace(zend_string *regex,
        pcre_cache_entry        *pce;                       /* Compiled regular expression */
        zend_string                     *result;                        /* Function result */
 
+       /* Abort on pending exception, e.g. thrown from __toString(). */
+       if (UNEXPECTED(EG(exception))) {
+               return NULL;
+       }
+
        /* Compile regex or get it from cache. */
        if ((pce = pcre_get_compiled_regex_cache(regex)) == NULL) {
                return NULL;
index 8e20108b8851664f09d53d3e4b357df9c3d2648f..780556956a6025635c7ec0655c3d77369d4e38fb 100644 (file)
@@ -24,7 +24,11 @@ foreach($regex_array as $regex_value) {
     var_dump(preg_replace($regex_value, $replace, $subject));
 }
 $regex_value = new stdclass(); //Object
-var_dump(preg_replace($regex_value, $replace, $subject));
+try {
+    var_dump(preg_replace($regex_value, $replace, $subject));
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 ?>
 --EXPECTF--
 *** Testing preg_replace() : error conditions***
@@ -54,5 +58,4 @@ string(1) "a"
 
 Arg value is /[a-zA-Z]/
 string(1) "1"
-
-Recoverable fatal error: Object of class stdClass could not be converted to string in %spreg_replace_error1.php on line %d
+Object of class stdClass could not be converted to string
index 8c826587ea4e4d31eee3c5c2bc8a166cb8f763a6..a334b2fefdf6d743c3e51312d04588b1ff2bf1b0 100644 (file)
@@ -19,7 +19,11 @@ foreach($replace as $value) {
     var_dump(preg_replace($regex, $value, $subject));
 }
 $value = new stdclass(); //Object
-var_dump(preg_replace($regex, $value, $subject));
+try {
+    var_dump(preg_replace($regex, $value, $subject));
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 echo "Done";
 ?>
 --EXPECTF--
@@ -32,5 +36,5 @@ Arg value is: Array
 
 Warning: preg_replace(): Parameter mismatch, pattern is a string while replacement is an array in %spreg_replace_error2.php on line %d
 bool(false)
-
-Recoverable fatal error: Object of class stdClass could not be converted to string in %spreg_replace_error2.php on line %d
+Object of class stdClass could not be converted to string
+Done
index 5950cdc38e6574c5eac3111a790326d6b4b0bfe7..b04e2fb928b7d006ae6badb4efb01e5f17d078f1 100644 (file)
@@ -269,7 +269,8 @@ safe:
 
                                                default:
                                                        buf = zval_get_string(parameter);
-                                                       if (!stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf),
+                                                       if (EG(exception) ||
+                                                               !stmt->dbh->methods->quoter(stmt->dbh, ZSTR_VAL(buf),
                                                                        ZSTR_LEN(buf), &plc->quoted, &plc->qlen,
                                                                        param_type)) {
                                                                /* bork */
index 92e594c76b70eee3325a6bdf61e76b18fbc04e97..bd93ca3cb2657ee467ce848b52f8da06c2eb6f9e 100644 (file)
@@ -307,7 +307,9 @@ static int really_register_bound_param(struct pdo_bound_param_data *param, pdo_s
                        ZVAL_STRINGL(parameter, p, len);
                        efree(p);
                } else {
-                       convert_to_string(parameter);
+                       if (!try_convert_to_string(parameter)) {
+                               return 0;
+                       }
                }
        } else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT && (Z_TYPE_P(parameter) == IS_FALSE || Z_TYPE_P(parameter) == IS_TRUE)) {
                convert_to_long(parameter);
@@ -911,7 +913,9 @@ static int do_fetch(pdo_stmt_t *stmt, int do_bind, zval *return_value, enum pdo_
 
                                        fetch_value(stmt, &val, i++, NULL);
                                        if (Z_TYPE(val) != IS_NULL) {
-                                               convert_to_string(&val);
+                                               if (!try_convert_to_string(&val)) {
+                                                       return 0;
+                                               }
                                                if ((cep = zend_lookup_class(Z_STR(val))) == NULL) {
                                                        stmt->fetch.cls.ce = ZEND_STANDARD_CLASS_DEF_PTR;
                                                } else {
@@ -2180,7 +2184,9 @@ static zval *dbstmt_prop_write(zval *object, zval *member, zval *value, void **c
 {
        pdo_stmt_t *stmt = Z_PDO_STMT_P(object);
 
-       convert_to_string(member);
+       if (!try_convert_to_string(member)) {
+               return value;
+       }
 
        if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
@@ -2194,7 +2200,9 @@ static void dbstmt_prop_delete(zval *object, zval *member, void **cache_slot)
 {
        pdo_stmt_t *stmt = Z_PDO_STMT_P(object);
 
-       convert_to_string(member);
+       if (!try_convert_to_string(member)) {
+               return;
+       }
 
        if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
                pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
@@ -2459,7 +2467,10 @@ static zval *row_prop_read(zval *object, zval *member, int type, void **cache_sl
                                fetch_value(stmt, rv, lval, NULL);
                        }
                } else {
-                       convert_to_string(member);
+                       if (!try_convert_to_string(member)) {
+                               return &EG(uninitialized_zval);
+                       }
+
                        /* TODO: replace this with a hash of available column names to column
                         * numbers */
                        for (colno = 0; colno < stmt->column_count; colno++) {
@@ -2511,7 +2522,9 @@ static int row_prop_exists(zval *object, zval *member, int check_empty, void **c
                                return lval >=0 && lval < stmt->column_count;
                        }
                } else {
-                       convert_to_string(member);
+                       if (!try_convert_to_string(member)) {
+                               return 0;
+                       }
                }
 
                /* TODO: replace this with a hash of available column names to column
index d17b168c2d79b35eb08dc58bfd97c6fa8035c063..d057857fa63ff8bef1ba2c58395709150449803e 100644 (file)
@@ -215,7 +215,7 @@ static inline zend_string *pdo_attr_strval(zval *options, enum pdo_attribute_typ
        zval *v;
 
        if (options && (v = zend_hash_index_find(Z_ARRVAL_P(options), option_name))) {
-               return zval_get_string(v);
+               return zval_try_get_string(v);
        }
        return defval ? zend_string_copy(defval) : NULL;
 }
index 6c83717e653c119827daa2734e825cb48cd09fd6..a4ff7e5c5a78e99faea08101829c654e9c3e9526 100644 (file)
@@ -466,6 +466,9 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
                case PDO_FB_ATTR_DATE_FORMAT:
                        {
                                zend_string *str = zval_get_string(val);
+                               if (EG(exception)) {
+                                       return 0;
+                               }
                                if (H->date_format) {
                                        efree(H->date_format);
                                }
@@ -477,6 +480,9 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
                case PDO_FB_ATTR_TIME_FORMAT:
                        {
                                zend_string *str = zval_get_string(val);
+                               if (EG(exception)) {
+                                       return 0;
+                               }
                                if (H->time_format) {
                                        efree(H->time_format);
                                }
@@ -488,6 +494,9 @@ static int firebird_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *v
                case PDO_FB_ATTR_TIMESTAMP_FORMAT:
                        {
                                zend_string *str = zval_get_string(val);
+                               if (EG(exception)) {
+                                       return 0;
+                               }
                                if (H->timestamp_format) {
                                        efree(H->timestamp_format);
                                }
index af71007b56aee0fe74d9c231abc26223df28c520..aee748d0e14bb8cf12ec754c7069a15532e50a3b 100644 (file)
@@ -728,7 +728,9 @@ static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, zend_long attr, zval *v
                default:
                        return 0;
                case PDO_ATTR_CURSOR_NAME:
-                       convert_to_string(val);
+                       if (!try_convert_to_string(val)) {
+                               return 0;
+                       }
 
                        if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
                                RECORD_ERROR(stmt);
index 607069008d61ac2918e4428382b9630cc17c85b7..f121b4791bf2ebe8df62e5205b296c4ce820f329 100644 (file)
@@ -461,6 +461,9 @@ static int oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /
                {
 #if (OCI_MAJOR_VERSION >= 10)
                        zend_string *action = zval_get_string(val);
+                       if (EG(exception)) {
+                               return 0;
+                       }
 
                        H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
                                (dvoid *) ZSTR_VAL(action), (ub4) ZSTR_LEN(action),
@@ -479,6 +482,9 @@ static int oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /
                {
 #if (OCI_MAJOR_VERSION >= 10)
                        zend_string *client_info = zval_get_string(val);
+                       if (EG(exception)) {
+                               return 0;
+                       }
 
                        H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
                                (dvoid *) ZSTR_VAL(client_info), (ub4) ZSTR_LEN(client_info),
@@ -497,6 +503,9 @@ static int oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /
                {
 #if (OCI_MAJOR_VERSION >= 10)
                        zend_string *identifier = zval_get_string(val);
+                       if (EG(exception)) {
+                               return 0;
+                       }
 
                        H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
                                (dvoid *) ZSTR_VAL(identifier), (ub4) ZSTR_LEN(identifier),
@@ -515,6 +524,9 @@ static int oci_handle_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val) /
                {
 #if (OCI_MAJOR_VERSION >= 10)
                        zend_string *module = zval_get_string(val);
+                       if (EG(exception)) {
+                               return 0;
+                       }
 
                        H->last_err = OCIAttrSet(H->session, OCI_HTYPE_SESSION,
                                (dvoid *) ZSTR_VAL(module), (ub4) ZSTR_LEN(module),
index 79733c2c5706a90e2e7a6c121ac86ec3ce8f36ec..b983f201165399d501e98f550a43e0e9d32dd483 100644 (file)
@@ -221,7 +221,9 @@ static sb4 oci_bind_input_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, dv
                *alenp = -1;
        } else if (!P->thing) {
                /* regular string bind */
-               convert_to_string(parameter);
+               if (!try_convert_to_string(parameter)) {
+                       return OCI_ERROR;
+               }
                *bufpp = Z_STRVAL_P(parameter);
                *alenp = (ub4) Z_STRLEN_P(parameter);
        }
@@ -260,8 +262,7 @@ static sb4 oci_bind_output_cb(dvoid *ctx, OCIBind *bindp, ub4 iter, ub4 index, d
                return OCI_CONTINUE;
        }
 
-       convert_to_string(parameter);
-       zval_ptr_dtor_str(parameter);
+       zval_ptr_dtor(parameter);
 
        Z_STR_P(parameter) = zend_string_alloc(param->max_value_len, 1);
        P->used_for_output = 1;
index e8b748a36f1983eb8a55d1970dccbbc696707316..5aae5d0a38fcb91fd92abac6f03ec4d686e26e96 100644 (file)
@@ -592,7 +592,10 @@ static PHP_METHOD(PDO, pgsqlCopyFromArray)
                PQclear(pgsql_result);
                ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pg_rows), tmp) {
                        size_t query_len;
-                       convert_to_string_ex(tmp);
+                       if (!try_convert_to_string(tmp)) {
+                               efree(query);
+                               return;
+                       }
 
                        if (buffer_len < Z_STRLEN_P(tmp)) {
                                buffer_len = Z_STRLEN_P(tmp);
index 02342e9fe4338bc1466a99bac660b8e20c4e419f..9e86a823234136637586ff116912bd065d02be1a 100644 (file)
@@ -411,7 +411,10 @@ static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
                                        break;
 
                                default:
-                                       convert_to_string_ex(&retval);
+                                       if (!try_convert_to_string(&retval)) {
+                                               ret = FAILURE;
+                                               break;
+                                       }
                                        sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
                                        break;
                        }
index 186bf182b166d0acf53bb884e8ce4a0bde9220d8..d8a68efb05205458074e7e6149f7b78312f43ceb 100644 (file)
@@ -153,7 +153,9 @@ static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_d
                                                        pdo_sqlite_error_stmt(stmt);
                                                        return 0;
                                                } else {
-                                                       convert_to_string(parameter);
+                                                       if (!try_convert_to_string(parameter)) {
+                                                               return 0;
+                                                       }
                                                }
 
                                                if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
@@ -176,7 +178,9 @@ static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_d
                                                                return 1;
                                                        }
                                                } else {
-                                                       convert_to_string(parameter);
+                                                       if (!try_convert_to_string(parameter)) {
+                                                               return 0;
+                                                       }
                                                        if (SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
                                                                        Z_STRVAL_P(parameter),
                                                                        Z_STRLEN_P(parameter),
diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_tostring_exception.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_tostring_exception.phpt
new file mode 100644 (file)
index 0000000..b1cd78e
--- /dev/null
@@ -0,0 +1,45 @@
+--TEST--
+__toString() exception during PDO Sqlite parameter binding
+--SKIPIF--
+<?php if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; ?>
+--FILE--
+<?php
+
+class throws {
+    function __toString() {
+        throw new Exception("Sorry");
+    }
+}
+
+$db = new PDO('sqlite::memory:');
+$db->exec('CREATE TABLE t(id int, v varchar(255))');
+
+$stmt = $db->prepare('INSERT INTO t VALUES(:i, :v)');
+$param1 = 1234;
+$stmt->bindValue('i', $param1);
+$param2 = "foo";
+$stmt->bindParam('v', $param2);
+
+$param2 = new throws;
+
+try {
+    $stmt->execute();
+} catch (Exception $e) {
+    echo "Exception thrown ...\n";
+}
+
+try {
+    $stmt->execute();
+} catch (Exception $e) {
+    echo "Exception thrown ...\n";
+}
+
+$query = $db->query("SELECT * FROM t");
+while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
+    print_r($row);
+}
+
+?>
+--EXPECT--
+Exception thrown ...
+Exception thrown ...
index 1be592a319ab5da06cf1b95a476b00b4fab30fe7..9dd08f249a194d901ee39c91605b9ffb27b8c392 100644 (file)
@@ -1330,6 +1330,11 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                smart_str_appendl(&str, Z_STRVAL(args[i]), Z_STRLEN(args[i]));
        }
 
+       /* Exception thrown during a string conversion. */
+       if (EG(exception)) {
+               goto cleanup;
+       }
+
        smart_str_0(&str);
 
        if (ZEND_NUM_ARGS() == 1) { /* new style, using connection string */
@@ -3045,7 +3050,6 @@ static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
 
        switch (Z_TYPE_P(field)) {
                case IS_STRING:
-                       convert_to_string_ex(field);
                        field_offset = PQfnumber(pgsql_result, Z_STRVAL_P(field));
                        if (field_offset < 0 || field_offset >= PQnfields(pgsql_result)) {
                                php_error_docref(NULL, E_WARNING, "Bad column offset specified");
@@ -4280,22 +4284,23 @@ PHP_FUNCTION(pg_copy_from)
                                PQclear(pgsql_result);
 #if HAVE_PQPUTCOPYDATA
                                ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pg_rows), value) {
-                                       zval tmp;
-                                       ZVAL_COPY(&tmp, value);
-                                       convert_to_string_ex(&tmp);
-                                       query = (char *)emalloc(Z_STRLEN(tmp) + 2);
-                                       strlcpy(query, Z_STRVAL(tmp), Z_STRLEN(tmp) + 2);
-                                       if(Z_STRLEN(tmp) > 0 && *(query + Z_STRLEN(tmp) - 1) != '\n') {
-                                               strlcat(query, "\n", Z_STRLEN(tmp) + 2);
+                                       zend_string *tmp = zval_get_string(value);
+                                       if (EG(exception)) {
+                                               return;
+                                       }
+                                       query = (char *)emalloc(ZSTR_LEN(tmp) + 2);
+                                       strlcpy(query, ZSTR_VAL(tmp), ZSTR_LEN(tmp) + 2);
+                                       if (ZSTR_LEN(tmp) > 0 && *(query + ZSTR_LEN(tmp) - 1) != '\n') {
+                                               strlcat(query, "\n", ZSTR_LEN(tmp) + 2);
                                        }
                                        if (PQputCopyData(pgsql, query, (int)strlen(query)) != 1) {
                                                efree(query);
-                                               zval_ptr_dtor_str(&tmp);
+                                               zend_string_release(tmp);
                                                PHP_PQ_ERROR("copy failed: %s", pgsql);
                                                RETURN_FALSE;
                                        }
                                        efree(query);
-                                       zval_ptr_dtor_str(&tmp);
+                                       zend_string_release(tmp);
                                } ZEND_HASH_FOREACH_END();
 
                                if (PQputCopyEnd(pgsql, NULL) != 1) {
@@ -4304,22 +4309,23 @@ PHP_FUNCTION(pg_copy_from)
                                }
 #else
                                ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pg_rows), value) {
-                                       zval tmp;
-                                       ZVAL_COPY(&tmp, value);
-                                       convert_to_string_ex(&tmp);
-                                       query = (char *)emalloc(Z_STRLEN(tmp) + 2);
-                                       strlcpy(query, Z_STRVAL(tmp), Z_STRLEN(tmp) + 2);
-                                       if(Z_STRLEN(tmp) > 0 && *(query + Z_STRLEN(tmp) - 1) != '\n') {
-                                               strlcat(query, "\n", Z_STRLEN(tmp) + 2);
+                                       zend_string *tmp = zval_get_string(value);
+                                       if (EG(exception)) {
+                                               return;
+                                       }
+                                       query = (char *)emalloc(ZSTR_LEN(tmp) + 2);
+                                       strlcpy(query, ZSTR_LVAL(tmp), ZSTR_LEN(tmp) + 2);
+                                       if (ZSTR_LEN(tmp) > 0 && *(query + ZSTR_LEN(tmp) - 1) != '\n') {
+                                               strlcat(query, "\n", ZSTR_LEN(tmp) + 2);
                                        }
                                        if (PQputline(pgsql, query)==EOF) {
                                                efree(query);
-                                               zval_ptr_dtor_str(&tmp);
+                                               zend_string_release(tmp);
                                                PHP_PQ_ERROR("copy failed: %s", pgsql);
                                                RETURN_FALSE;
                                        }
                                        efree(query);
-                                       zval_ptr_dtor_str(&tmp);
+                                       zend_string_release(tmp);
                                } ZEND_HASH_FOREACH_END();
 
                                if (PQputline(pgsql, "\\.\n") == EOF) {
@@ -5167,17 +5173,13 @@ PHP_FUNCTION(pg_send_execute)
                        if (Z_TYPE_P(tmp) == IS_NULL) {
                                params[i] = NULL;
                        } else {
-                               zval tmp_val;
-                               ZVAL_COPY(&tmp_val, tmp);
-                               convert_to_string(&tmp_val);
-                               if (Z_TYPE(tmp_val) != IS_STRING) {
-                                       php_error_docref(NULL, E_WARNING,"Error converting parameter");
-                                       zval_ptr_dtor(&tmp_val);
+                               zend_string *tmp_str = zval_get_string(tmp);
+                               if (EG(exception)) {
                                        _php_pgsql_free_params(params, num_params);
-                                       RETURN_FALSE;
+                                       return;
                                }
-                               params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
-                               zval_ptr_dtor(&tmp_val);
+                               params[i] = estrndup(ZSTR_VAL(tmp_str), ZSTR_LEN(tmp_str));
+                               zend_string_release(tmp_str);
                        }
 
                        i++;
@@ -6103,8 +6105,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
                                                break;
 
                                        case IS_LONG:
-                                               ZVAL_LONG(&new_val, Z_LVAL_P(val));
-                                               convert_to_string_ex(&new_val);
+                                               ZVAL_STR(&new_val, zend_long_to_str(Z_LVAL_P(val)));
                                                break;
 
                                        case IS_DOUBLE:
@@ -6412,8 +6413,7 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con
                                                break;
 
                                        case IS_LONG:
-                                               ZVAL_LONG(&new_val, Z_LVAL_P(val));
-                                               convert_to_string_ex(&new_val);
+                                               ZVAL_STR(&new_val, zend_long_to_str(Z_LVAL_P(val)));
                                                break;
 
                                        case IS_DOUBLE:
index b66928ebd6abc992a47247ebd8047f8dc919ec6e..9c018bf9c859f4f9c65e746d059a424f94bcda12 100644 (file)
@@ -279,7 +279,9 @@ PHP_FUNCTION(readline_info)
                        oldstr = rl_line_buffer;
                        if (value) {
                                /* XXX if (rl_line_buffer) free(rl_line_buffer); */
-                               convert_to_string_ex(value);
+                               if (!try_convert_to_string(value)) {
+                                       return;
+                               }
                                rl_line_buffer = strdup(Z_STRVAL_P(value));
                        }
                        RETVAL_STRING(SAFE_STRING(oldstr));
@@ -302,7 +304,9 @@ PHP_FUNCTION(readline_info)
                } else if (!strcasecmp(what, "pending_input")) {
                        oldval = rl_pending_input;
                        if (value) {
-                               convert_to_string_ex(value);
+                               if (!try_convert_to_string(value)) {
+                                       return;
+                               }
                                rl_pending_input = Z_STRVAL_P(value)[0];
                        }
                        RETVAL_LONG(oldval);
@@ -319,7 +323,9 @@ PHP_FUNCTION(readline_info)
                } else if (!strcasecmp(what, "completion_append_character")) {
                        oldval = rl_completion_append_character;
                        if (value) {
-                               convert_to_string_ex(value)
+                               if (!try_convert_to_string(value)) {
+                                       return;
+                               }
                                rl_completion_append_character = (int)Z_STRVAL_P(value)[0];
                        }
                        RETVAL_INTERNED_STR(
@@ -342,7 +348,9 @@ PHP_FUNCTION(readline_info)
                        oldstr = (char*)rl_readline_name;
                        if (value) {
                                /* XXX if (rl_readline_name) free(rl_readline_name); */
-                               convert_to_string_ex(value);
+                               if (!try_convert_to_string(value)) {
+                                       return;
+                               }
                                rl_readline_name = strdup(Z_STRVAL_P(value));
                        }
                        RETVAL_STRING(SAFE_STRING(oldstr));
index e6ca3322cb353295a4e4a5d3c8da4c1c7873f81d..4623efb3cf970354e9bc2ed66b7b82e047dffe21 100644 (file)
@@ -2263,7 +2263,7 @@ ZEND_METHOD(reflection_parameter, __construct)
                case IS_ARRAY: {
                                zval *classref;
                                zval *method;
-                               zend_string *lcname;
+                               zend_string *name, *lcname;
 
                                if (((classref = zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
                                        || ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
@@ -2275,27 +2275,38 @@ ZEND_METHOD(reflection_parameter, __construct)
                                if (Z_TYPE_P(classref) == IS_OBJECT) {
                                        ce = Z_OBJCE_P(classref);
                                } else {
-                                       convert_to_string_ex(classref);
-                                       if ((ce = zend_lookup_class(Z_STR_P(classref))) == NULL) {
+                                       name = zval_get_string(classref);
+                                       if (EG(exception)) {
+                                               return;
+                                       }
+                                       if ((ce = zend_lookup_class(name)) == NULL) {
                                                zend_throw_exception_ex(reflection_exception_ptr, 0,
-                                                               "Class %s does not exist", Z_STRVAL_P(classref));
+                                                               "Class %s does not exist", ZSTR_VAL(name));
+                                               zend_string_release(name);
                                                return;
                                        }
+                                       zend_string_release(name);
+                               }
+
+                               name = zval_get_string(method);
+                               if (EG(exception)) {
+                                       return;
                                }
 
-                               convert_to_string_ex(method);
-                               lcname = zend_string_tolower(Z_STR_P(method));
+                               lcname = zend_string_tolower(name);
                                if (Z_TYPE_P(classref) == IS_OBJECT && is_closure_invoke(ce, lcname)
                                        && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
                                {
                                        /* nothing to do. don't set is_closure since is the invoke handler,
                                           not the closure itself */
                                } else if ((fptr = zend_hash_find_ptr(&ce->function_table, lcname)) == NULL) {
+                                       zend_string_release(name);
                                        zend_string_release(lcname);
                                        zend_throw_exception_ex(reflection_exception_ptr, 0,
                                                "Method %s::%s() does not exist", ZSTR_VAL(ce->name), Z_STRVAL_P(method));
                                        return;
                                }
+                               zend_string_release(name);
                                zend_string_release(lcname);
                        }
                        break;
@@ -2329,29 +2340,23 @@ ZEND_METHOD(reflection_parameter, __construct)
        if (Z_TYPE_P(parameter) == IS_LONG) {
                position= (int)Z_LVAL_P(parameter);
                if (position < 0 || (uint32_t)position >= num_args) {
-                       if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
-                               if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
-                                       zend_string_release_ex(fptr->common.function_name, 0);
-                               }
-                               zend_free_trampoline(fptr);
-                       }
-                       if (is_closure) {
-                               zval_ptr_dtor(reference);
-                       }
                        _DO_THROW("The parameter specified by its offset could not be found");
-                       return;
+                       goto failure;
                }
        } else {
                uint32_t i;
 
-               position= -1;
-               convert_to_string_ex(parameter);
+               position = -1;
+               if (!try_convert_to_string(parameter)) {
+                       goto failure;
+               }
+
                if (fptr->type == ZEND_INTERNAL_FUNCTION &&
                    !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
                        for (i = 0; i < num_args; i++) {
                                if (arg_info[i].name) {
                                        if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
-                                               position= i;
+                                               position = i;
                                                break;
                                        }
 
@@ -2361,24 +2366,15 @@ ZEND_METHOD(reflection_parameter, __construct)
                        for (i = 0; i < num_args; i++) {
                                if (arg_info[i].name) {
                                        if (strcmp(ZSTR_VAL(arg_info[i].name), Z_STRVAL_P(parameter)) == 0) {
-                                               position= i;
+                                               position = i;
                                                break;
                                        }
                                }
                        }
                }
                if (position == -1) {
-                       if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
-                               if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
-                                       zend_string_release_ex(fptr->common.function_name, 0);
-                               }
-                               zend_free_trampoline(fptr);
-                       }
-                       if (is_closure) {
-                               zval_ptr_dtor(reference);
-                       }
                        _DO_THROW("The parameter specified by its name could not be found");
-                       return;
+                       goto failure;
                }
        }
 
@@ -2406,6 +2402,18 @@ ZEND_METHOD(reflection_parameter, __construct)
        } else {
                ZVAL_NULL(prop_name);
        }
+       return;
+
+failure:
+       if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+               if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
+                       zend_string_release_ex(fptr->common.function_name, 0);
+               }
+               zend_free_trampoline(fptr);
+       }
+       if (is_closure) {
+               zval_ptr_dtor(reference);
+       }
 }
 /* }}} */
 
@@ -3692,7 +3700,10 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
                        ZVAL_COPY(&intern->obj, argument);
                }
        } else {
-               convert_to_string_ex(argument);
+               if (!try_convert_to_string(argument)) {
+                       return;
+               }
+
                if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
                        if (!EG(exception)) {
                                zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", Z_STRVAL_P(argument));
index 8e4e8e3a1828b568be1c7160aae75c7bd0cd27de..47f7604e8bc165482d322ee2ead0647941eb3a27 100644 (file)
@@ -19,4 +19,9 @@ $class = new ReflectionClass('A');
 echo $class;
 ?>
 --EXPECTF--
-Fatal error: Method ReflectionClass::__toString() must not throw an exception, caught Exception:  in %sbug74673.php on line %d
+Fatal error: Uncaught Exception in %s:%d
+Stack trace:
+#0 [internal function]: {closure}(2, 'Use of undefine...', %s, %d, Array)
+#1 %s(%d): ReflectionClass->__toString()
+#2 {main}
+  thrown in %s on line %d
index bf3ddee0d58ef782aba71faa0942b7f7621e8745..671968e8da30e57ee02d32f8c15ffb2a7a8b2ca7 100644 (file)
@@ -1752,35 +1752,36 @@ static PHP_FUNCTION(session_set_cookie_params)
                lifetime = zval_get_string(lifetime_or_options);
        }
 
+       /* Exception during string conversion */
+       if (EG(exception)) {
+               goto cleanup;
+       }
+
        if (lifetime) {
                ini_name = zend_string_init("session.cookie_lifetime", sizeof("session.cookie_lifetime") - 1, 0);
                result = zend_alter_ini_entry(ini_name, lifetime, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
-               zend_string_release(lifetime);
                zend_string_release_ex(ini_name, 0);
                if (result == FAILURE) {
-                       RETURN_FALSE;
+                       RETVAL_FALSE;
+                       goto cleanup;
                }
        }
        if (path) {
                ini_name = zend_string_init("session.cookie_path", sizeof("session.cookie_path") - 1, 0);
                result = zend_alter_ini_entry(ini_name, path, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
-               if (found > 0) {
-                       zend_string_release(path);
-               }
                zend_string_release_ex(ini_name, 0);
                if (result == FAILURE) {
-                       RETURN_FALSE;
+                       RETVAL_FALSE;
+                       goto cleanup;
                }
        }
        if (domain) {
                ini_name = zend_string_init("session.cookie_domain", sizeof("session.cookie_domain") - 1, 0);
                result = zend_alter_ini_entry(ini_name, domain, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
-               if (found > 0) {
-                       zend_string_release(domain);
-               }
                zend_string_release_ex(ini_name, 0);
                if (result == FAILURE) {
-                       RETURN_FALSE;
+                       RETVAL_FALSE;
+                       goto cleanup;
                }
        }
        if (!secure_null) {
@@ -1788,7 +1789,8 @@ static PHP_FUNCTION(session_set_cookie_params)
                result = zend_alter_ini_entry_chars(ini_name, secure ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
                zend_string_release_ex(ini_name, 0);
                if (result == FAILURE) {
-                       RETURN_FALSE;
+                       RETVAL_FALSE;
+                       goto cleanup;
                }
        }
        if (!httponly_null) {
@@ -1796,22 +1798,29 @@ static PHP_FUNCTION(session_set_cookie_params)
                result = zend_alter_ini_entry_chars(ini_name, httponly ? "1" : "0", 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
                zend_string_release_ex(ini_name, 0);
                if (result == FAILURE) {
-                       RETURN_FALSE;
+                       RETVAL_FALSE;
+                       goto cleanup;
                }
        }
        if (samesite) {
                ini_name = zend_string_init("session.cookie_samesite", sizeof("session.cookie_samesite") - 1, 0);
                result = zend_alter_ini_entry(ini_name, samesite, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
-               if (found > 0) {
-                       zend_string_release(samesite);
-               }
                zend_string_release_ex(ini_name, 0);
                if (result == FAILURE) {
-                       RETURN_FALSE;
+                       RETVAL_FALSE;
+                       goto cleanup;
                }
        }
 
-       RETURN_TRUE;
+       RETVAL_TRUE;
+
+cleanup:
+       if (lifetime) zend_string_release(lifetime);
+       if (found > 0) {
+               if (path) zend_string_release(path);
+               if (domain) zend_string_release(domain);
+               if (samesite) zend_string_release(samesite);
+       }
 }
 /* }}} */
 
@@ -2364,7 +2373,10 @@ static PHP_FUNCTION(session_cache_expire)
        RETVAL_LONG(PS(cache_expire));
 
        if (expires) {
-               convert_to_string_ex(expires);
+               if (!try_convert_to_string(expires)) {
+                       return;
+               }
+
                ini_name = zend_string_init("session.cache_expire", sizeof("session.cache_expire") - 1, 0);
                zend_alter_ini_entry(ini_name, Z_STR_P(expires), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
                zend_string_release_ex(ini_name, 0);
index fb55b6b195a0913ec3198544aacc6702475c3096..01c119888e32012c54d15ceae0f603efa2a7d3dc 100644 (file)
@@ -260,6 +260,9 @@ long_dim:
                        if (Z_TYPE_P(member) != IS_STRING) {
                                ZVAL_STR(&tmp_zv, zval_get_string_func(member));
                                member = &tmp_zv;
+                               if (EG(exception)) {
+                                       return &EG(uninitialized_zval);
+                               }
                        }
                        name = Z_STRVAL_P(member);
                }
@@ -455,6 +458,10 @@ long_dim:
                } else {
                        if (Z_TYPE_P(member) != IS_STRING) {
                                trim_str = zval_get_string_func(member);
+                               if (EG(exception)) {
+                                       return &EG(error_zval);
+                               }
+
                                ZVAL_STR(&tmp_zv, php_trim(trim_str, NULL, 0, 3));
                                zend_string_release_ex(trim_str, 0);
                                member = &tmp_zv;
@@ -672,10 +679,12 @@ static zval *sxe_property_get_adr(zval *object, zval *member, int fetch_type, vo
        char           *name;
        SXE_ITER        type;
 
-       sxe = Z_SXEOBJ_P(object);
+       if (!try_convert_to_string(member)) {
+               return NULL;
+       }
 
+       sxe = Z_SXEOBJ_P(object);
        GET_NODE(sxe, node);
-       convert_to_string(member);
        name = Z_STRVAL_P(member);
        node = sxe_get_element_by_name(sxe, node, &name, &type);
        if (node) {
@@ -713,6 +722,9 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend
        if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
                ZVAL_STR(&tmp_zv, zval_get_string_func(member));
                member = &tmp_zv;
+               if (EG(exception)) {
+                       return 0;
+               }
        }
 
        sxe = Z_SXEOBJ_P(object);
@@ -832,6 +844,9 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements,
        if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
                ZVAL_STR(&tmp_zv, zval_get_string_func(member));
                member = &tmp_zv;
+               if (EG(exception)) {
+                       return;
+               }
        }
 
        sxe = Z_SXEOBJ_P(object);
index 34e951b6ecbd079d41ba9205ed480c3d32b59630..69ff9b00f493ebdf56c32542101ac55987f2fc84 100644 (file)
@@ -1920,6 +1920,9 @@ zval *php_snmp_read_property(zval *object, zval *member, int type, void **cache_
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return &EG(uninitialized_zval);
+               }
        }
 
        hnd = zend_hash_find_ptr(&php_snmp_properties, Z_STR_P(member));
@@ -1954,6 +1957,9 @@ zval *php_snmp_write_property(zval *object, zval *member, zval *value, void **ca
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return value;
+               }
        }
 
        obj = Z_SNMP_P(object);
index a9f287a8eaac95f6a53b433ef9fbe90589f0f721..f24e0926cee22e5758269055d51994595b164088 100644 (file)
@@ -332,7 +332,10 @@ double_case:
                zend_long lval;
                double dval;
 
-               convert_to_string(&lzval);
+               if (!try_convert_to_string(&lzval)) {
+                       ctx->err.has_error = 1;
+                       break;
+               }
 
                switch (is_numeric_string(Z_STRVAL(lzval), Z_STRLEN(lzval), &lval, &dval, 0)) {
                case IS_DOUBLE:
index 697d5f1d9118a2f7434b4491b75a693b8a9aecb9..defb9fdb88eeeb22778f0a171ca0a7eb11b0b273 100644 (file)
@@ -1066,23 +1066,18 @@ static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *objec
 {
        zend_object_iterator      *iterator = object->iterators[object->level].iterator;
        zval                      *data;
-       zend_error_handling        error_handling;
 
        data = iterator->funcs->get_current_data(iterator);
-
-       /* Replace exception handling so the catchable fatal error that is thrown when a class
-        * without __toString is converted to string is converted into an exception. */
-       zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling);
        if (data) {
                ZVAL_DEREF(data);
+               /* TODO: Remove this special case? */
                if (Z_TYPE_P(data) == IS_ARRAY) {
-                       ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1);
+                       RETVAL_INTERNED_STR(ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED));
                } else {
                        ZVAL_COPY(return_value, data);
                        convert_to_string(return_value);
                }
        }
-       zend_restore_error_handling(&error_handling);
 }
 
 static void spl_recursive_tree_iterator_get_postfix(spl_recursive_it_object *object, zval *return_value)
@@ -2006,7 +2001,7 @@ SPL_METHOD(RegexIterator, accept)
        spl_dual_it_object *intern;
        zend_string *result, *subject;
        size_t count = 0;
-       zval zcount, *replacement, tmp_replacement, rv;
+       zval zcount, rv;
        pcre2_match_data *match_data;
        pcre2_code *re;
        int rc;
@@ -2030,6 +2025,11 @@ SPL_METHOD(RegexIterator, accept)
                subject = zval_get_string(&intern->current.data);
        }
 
+       /* Exception during string conversion. */
+       if (EG(exception)) {
+               return;
+       }
+
        switch (intern->u.regex.mode)
        {
                case REGIT_MODE_MAX: /* won't happen but makes compiler happy */
@@ -2061,14 +2061,14 @@ SPL_METHOD(RegexIterator, accept)
                        RETVAL_BOOL(count > 1);
                        break;
 
-               case REGIT_MODE_REPLACE:
-                       replacement = zend_read_property(intern->std.ce, ZEND_THIS, "replacement", sizeof("replacement")-1, 1, &rv);
-                       if (Z_TYPE_P(replacement) != IS_STRING) {
-                               ZVAL_COPY(&tmp_replacement, replacement);
-                               convert_to_string(&tmp_replacement);
-                               replacement = &tmp_replacement;
+               case REGIT_MODE_REPLACE: {
+                       zval *replacement = zend_read_property(intern->std.ce, ZEND_THIS, "replacement", sizeof("replacement")-1, 1, &rv);
+                       zend_string *replacement_str = zval_get_string(replacement);
+                       if (EG(exception)) {
+                               return;
                        }
-                       result = php_pcre_replace_impl(intern->u.regex.pce, subject, ZSTR_VAL(subject), ZSTR_LEN(subject), Z_STR_P(replacement), -1, &count);
+
+                       result = php_pcre_replace_impl(intern->u.regex.pce, subject, ZSTR_VAL(subject), ZSTR_LEN(subject), replacement_str, -1, &count);
 
                        if (intern->u.regex.flags & REGIT_USE_KEY) {
                                zval_ptr_dtor(&intern->current.key);
@@ -2078,10 +2078,9 @@ SPL_METHOD(RegexIterator, accept)
                                ZVAL_STR(&intern->current.data, result);
                        }
 
-                       if (replacement == &tmp_replacement) {
-                               zval_ptr_dtor(replacement);
-                       }
+                       zend_string_release(replacement_str);
                        RETVAL_BOOL(count > 0);
+               }
        }
 
        if (intern->u.regex.flags & REGIT_INVERTED) {
index 74d393b677d8b988dbb436851918c5ed05353243..07a1f79134e9306439014d6ffd4deb4c9ace8386 100644 (file)
@@ -18,4 +18,9 @@ test(new CachingIterator($ar, 0));
 ?>
 ===DONE===
 --EXPECTF--
-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
+Fatal error: Uncaught BadMethodCallException: CachingIterator does not fetch string value (see CachingIterator::__construct) in %s:%d
+Stack trace:
+#0 %s(%d): CachingIterator->__toString()
+#1 %s(%d): test(Object(CachingIterator))
+#2 {main}
+  thrown in %s on line %d
index 7374a066fa2e28721da1cd79e6d75cf470cd0c0b..a017254df0240a313f58bec18ee5e0cfa91ab24f 100644 (file)
@@ -22,12 +22,12 @@ try {
        foreach(new RecursiveTreeIterator($it) as $k => $v) {
                echo "[$k] => $v\n";
        }
-} catch (UnexpectedValueException $e) {
-       echo "UnexpectedValueException thrown\n";
+} catch (Error $e) {
+       echo $e->getMessage(), "\n";
 }
 
 ?>
 ===DONE===
 --EXPECT--
-UnexpectedValueException thrown
+Object of class stdClass could not be converted to string
 ===DONE===
index b993d622ff9771de20f48d0776628a10fec2cdeb..c3ffeabc0011091ed3d2b2f9f51070b3274373bf 100644 (file)
@@ -801,10 +801,16 @@ static int sqlite3_do_callback(struct php_sqlite3_fci *fc, zval *cb, int argc, s
                                        sqlite3_result_double(context, Z_DVAL(retval));
                                        break;
 
-                               default:
-                                       convert_to_string_ex(&retval);
-                                       sqlite3_result_text(context, Z_STRVAL(retval), Z_STRLEN(retval), SQLITE_TRANSIENT);
+                               default: {
+                                       zend_string *str = zval_get_string(&retval);
+                                       if (EG(exception)) {
+                                               ret = FAILURE;
+                                               break;
+                                       }
+                                       sqlite3_result_text(context, ZSTR_VAL(str), ZSTR_LEN(str), SQLITE_TRANSIENT);
+                                       zend_string_release(str);
                                        break;
+                               }
                        }
                } else {
                        sqlite3_result_error(context, "failed to invoke callback", 0);
@@ -1480,13 +1486,18 @@ static int php_sqlite3_bind_params(php_sqlite3_stmt *stmt_obj) /* {{{ */
                                        break;
                                }
 
-                               case SQLITE3_TEXT:
-                                       convert_to_string(parameter);
-                                       return_code = sqlite3_bind_text(stmt_obj->stmt, param->param_number, Z_STRVAL_P(parameter), Z_STRLEN_P(parameter), SQLITE_STATIC);
+                               case SQLITE3_TEXT: {
+                                       zend_string *str = zval_get_string(parameter);
+                                       if (EG(exception)) {
+                                               return FAILURE;
+                                       }
+                                       return_code = sqlite3_bind_text(stmt_obj->stmt, param->param_number, ZSTR_VAL(str), ZSTR_LEN(str), SQLITE_TRANSIENT);
                                        if (return_code != SQLITE_OK) {
                                                php_sqlite3_error(stmt_obj->db_obj, "Unable to bind parameter number " ZEND_LONG_FMT " (%d)", param->param_number, return_code);
                                        }
+                                       zend_string_release(str);
                                        break;
+                               }
 
                                case SQLITE_NULL:
                                        return_code = sqlite3_bind_null(stmt_obj->stmt, param->param_number);
@@ -1526,7 +1537,7 @@ PHP_METHOD(sqlite3stmt, getSQL)
 
        bind_rc = php_sqlite3_bind_params(stmt_obj);
 
-       if (bind_rc == FAILURE) {
+       if (bind_rc == FAILURE || EG(exception)) {
                RETURN_FALSE;
        }
 
@@ -1718,7 +1729,7 @@ PHP_METHOD(sqlite3stmt, execute)
        /* Bind parameters to the statement */
        bind_rc = php_sqlite3_bind_params(stmt_obj);
 
-       if (bind_rc == FAILURE) {
+       if (bind_rc == FAILURE || EG(exception)) {
                RETURN_FALSE;
        }
 
diff --git a/ext/sqlite3/tests/exception_from_toString.phpt b/ext/sqlite3/tests/exception_from_toString.phpt
new file mode 100644 (file)
index 0000000..1d6ed39
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Check that exceptions from __toString() are handled correctly
+--FILE--
+<?php
+
+class throws {
+    function __toString() {
+        throw new Exception("Sorry");
+    }
+}
+
+$db = new sqlite3(':memory:');
+$db->exec('CREATE TABLE t(id int, v varchar(255))');
+
+$stmt = $db->prepare('INSERT INTO t VALUES(:i, :v)');
+$stmt->bindValue('i', 1234);
+$stmt->bindValue('v', new throws);
+
+try {
+    $stmt->execute();
+} catch (Exception $e) {
+    echo "Exception thrown ...\n";
+}
+
+try {
+    $stmt->execute();
+} catch (Exception $e) {
+    echo "Exception thrown ...\n";
+}
+
+$query = $db->query("SELECT * FROM t");
+while ($row = $query->fetchArray(SQLITE3_ASSOC)) {
+    print_r($row);
+}
+
+?>
+--EXPECT--
+Exception thrown ...
+Exception thrown ...
index 5448a1815d33fbf9e23475efa40f2410a4873b27..71a7cf17e7c41cd9cbedbabe4e89b8b09dcf01d3 100644 (file)
@@ -2458,7 +2458,10 @@ PHP_FUNCTION(extract)
        }
 
        if (prefix) {
-               convert_to_string(prefix);
+               if (!try_convert_to_string(prefix)) {
+                       return;
+               }
+
                if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
                        php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier");
                        return;
@@ -4134,7 +4137,9 @@ zend_bool array_column_param_helper(zval *param,
                        return 1;
 
                case IS_OBJECT:
-                       convert_to_string_ex(param);
+                       if (!try_convert_to_string(param)) {
+                               return 0;
+                       }
                        /* fallthrough */
                case IS_STRING:
                        return 1;
index eb1b59db7444b98e9f44700d82a25d61c48821a4..6e21af6dd5e50dd1014a33e1c8330dc3694f9167 100644 (file)
@@ -300,6 +300,10 @@ PHP_FUNCTION(assert_options)
                oldint = ASSERTG(active);
                if (ac == 2) {
                        zend_string *value_str = zval_get_string(value);
+                       if (EG(exception)) {
+                               return;
+                       }
+
                        key = zend_string_init("assert.active", sizeof("assert.active")-1, 0);
                        zend_alter_ini_entry_ex(key, value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0);
                        zend_string_release_ex(key, 0);
@@ -312,6 +316,10 @@ PHP_FUNCTION(assert_options)
                oldint = ASSERTG(bail);
                if (ac == 2) {
                        zend_string *value_str = zval_get_string(value);
+                       if (EG(exception)) {
+                               return;
+                       }
+
                        key = zend_string_init("assert.bail", sizeof("assert.bail")-1, 0);
                        zend_alter_ini_entry_ex(key, value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0);
                        zend_string_release_ex(key, 0);
@@ -324,6 +332,10 @@ PHP_FUNCTION(assert_options)
                oldint = ASSERTG(quiet_eval);
                if (ac == 2) {
                        zend_string *value_str = zval_get_string(value);
+                       if (EG(exception)) {
+                               return;
+                       }
+
                        key = zend_string_init("assert.quiet_eval", sizeof("assert.quiet_eval")-1, 0);
                        zend_alter_ini_entry_ex(key, value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0);
                        zend_string_release_ex(key, 0);
@@ -336,6 +348,10 @@ PHP_FUNCTION(assert_options)
                oldint = ASSERTG(warning);
                if (ac == 2) {
                        zend_string *value_str = zval_get_string(value);
+                       if (EG(exception)) {
+                               return;
+                       }
+
                        key = zend_string_init("assert.warning", sizeof("assert.warning")-1, 0);
                        zend_alter_ini_entry_ex(key, value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0);
                        zend_string_release_ex(key, 0);
@@ -361,8 +377,12 @@ PHP_FUNCTION(assert_options)
        case ASSERT_EXCEPTION:
                oldint = ASSERTG(exception);
                if (ac == 2) {
-                       zend_string *key = zend_string_init("assert.exception", sizeof("assert.exception")-1, 0);
                        zend_string *val = zval_get_string(value);
+                       if (EG(exception)) {
+                               return;
+                       }
+
+                       key = zend_string_init("assert.exception", sizeof("assert.exception")-1, 0);
                        zend_alter_ini_entry_ex(key, val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0);
                        zend_string_release_ex(val, 0);
                        zend_string_release_ex(key, 0);
index 920974fe48acaf62a0d0e6aae39770500547f320..8d4dec48c11690745185fb96f040391879ef967b 100644 (file)
@@ -5357,7 +5357,10 @@ PHP_FUNCTION(highlight_string)
                Z_PARAM_OPTIONAL
                Z_PARAM_BOOL(i)
        ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
-       convert_to_string_ex(expr);
+
+       if (!try_convert_to_string(expr)) {
+               return;
+       }
 
        if (i) {
                php_output_start_default();
index 9d90558f59c2867c05a96c219c08cc543356d51e..83fcf2dcbf646b14ee5d78af80152199642bfbe5 100644 (file)
@@ -250,8 +250,6 @@ static php_stream_filter *strfilter_strip_tags_create(const char *filtername, zv
 
        php_error_docref(NULL, E_DEPRECATED, "The string.strip_tags filter is deprecated");
 
-       inst = pemalloc(sizeof(php_strip_tags_filter), persistent);
-
        if (filterparams != NULL) {
                if (Z_TYPE_P(filterparams) == IS_ARRAY) {
                        smart_str tags_ss = {0};
@@ -268,8 +266,17 @@ static php_stream_filter *strfilter_strip_tags_create(const char *filtername, zv
                } else {
                        allowed_tags = zval_get_string(filterparams);
                }
+
+               /* Exception during string conversion. */
+               if (EG(exception)) {
+                       if (allowed_tags) {
+                               zend_string_release(allowed_tags);
+                       }
+                       return NULL;
+               }
        }
 
+       inst = pemalloc(sizeof(php_strip_tags_filter), persistent);
        if (php_strip_tags_filter_ctor(inst, allowed_tags, persistent) == SUCCESS) {
                filter = php_stream_filter_alloc(&strfilter_strip_tags_ops, inst, persistent);
        } else {
index b804cda5002fcee6e2fafb99b122c10fcf366b88..4ee68adefa560f7d76ced286e800593932b47f0d 100644 (file)
@@ -400,7 +400,10 @@ php_formatted_print(zval *z_format, zval *args, int argc)
        int always_sign;
        size_t format_len;
 
-       convert_to_string_ex(z_format);
+       if (!try_convert_to_string(z_format)) {
+               return NULL;
+       }
+
        format = Z_STRVAL_P(z_format);
        format_len = Z_STRLEN_P(z_format);
        result = zend_string_alloc(size, 0);
index e8b5d5b171ee737cfa9b642e859ab14e2f4f77c2..f1b2fa4e8b658c35c17f2f4d2c6a26c4dce84efb 100644 (file)
@@ -258,10 +258,12 @@ PHP_FUNCTION(setcookie)
                }
        }
 
-       if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, 1) == SUCCESS) {
-               RETVAL_TRUE;
-       } else {
-               RETVAL_FALSE;
+       if (!EG(exception)) {
+               if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, 1) == SUCCESS) {
+                       RETVAL_TRUE;
+               } else {
+                       RETVAL_FALSE;
+               }
        }
 
        if (expires_or_options && Z_TYPE_P(expires_or_options) == IS_ARRAY) {
@@ -311,10 +313,12 @@ PHP_FUNCTION(setrawcookie)
                }
        }
 
-       if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, 0) == SUCCESS) {
-               RETVAL_TRUE;
-       } else {
-               RETVAL_FALSE;
+       if (!EG(exception)) {
+               if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, 0) == SUCCESS) {
+                       RETVAL_TRUE;
+               } else {
+                       RETVAL_FALSE;
+               }
        }
 
        if (expires_or_options && Z_TYPE_P(expires_or_options) == IS_ARRAY) {
index cefcd387693533d87cfcaf9696ec8f8a787300aa..840df9103e631c66629914f4a0f4005a3c3da5b4 100644 (file)
@@ -1090,7 +1090,10 @@ PHP_FUNCTION(base_convert)
                Z_PARAM_LONG(frombase)
                Z_PARAM_LONG(tobase)
        ZEND_PARSE_PARAMETERS_END();
-       convert_to_string_ex(number);
+
+       if (!try_convert_to_string(number)) {
+               return;
+       }
 
        if (frombase < 2 || frombase > 36) {
                php_error_docref(NULL, E_WARNING, "Invalid `from base' (" ZEND_LONG_FMT ")", frombase);
index 5f375585d412266c97fdfb5a24c3f978bf543fcc..3c0dc009f18409b1955cf369b59e8d639b8862b0 100644 (file)
@@ -297,7 +297,12 @@ PHP_FUNCTION(pack)
                                }
 
                                if (arg < 0) {
-                                       convert_to_string(&argv[currentarg]);
+                                       if (!try_convert_to_string(&argv[currentarg])) {
+                                               efree(formatcodes);
+                                               efree(formatargs);
+                                               return;
+                                       }
+
                                        arg = Z_STRLEN(argv[currentarg]);
                                        if (code == 'Z') {
                                                /* add one because Z is always NUL-terminated:
index 3f1ff6dd557335784a1e70087fac88ca7dcefb10..52ff1518e6250adc1c04d1069bc965ec62db606b 100644 (file)
@@ -140,6 +140,9 @@ static zend_string* php_password_get_salt(zval *unused_, size_t required_salt_le
                case IS_DOUBLE:
                case IS_OBJECT:
                        buffer = zval_get_string(option_buffer);
+                       if (EG(exception)) {
+                               return NULL;
+                       }
                        break;
                case IS_FALSE:
                case IS_TRUE:
index 326cfc14312f5f3201584dad39a1a6abc98c1f23..d76e1595f304949c8b3f002b7d19b51bba214b7c 100644 (file)
@@ -552,7 +552,9 @@ PHP_FUNCTION(proc_open)
                } else {
 
                        if ((ztype = zend_hash_index_find(Z_ARRVAL_P(descitem), 0)) != NULL) {
-                               convert_to_string_ex(ztype);
+                               if (!try_convert_to_string(ztype)) {
+                                       goto exit_fail;
+                               }
                        } else {
                                php_error_docref(NULL, E_WARNING, "Missing handle qualifier in array");
                                goto exit_fail;
@@ -563,7 +565,9 @@ PHP_FUNCTION(proc_open)
                                zval *zmode;
 
                                if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) {
-                                       convert_to_string_ex(zmode);
+                                       if (!try_convert_to_string(zmode)) {
+                                               goto exit_fail;
+                                       }
                                } else {
                                        php_error_docref(NULL, E_WARNING, "Missing mode parameter for 'pipe'");
                                        goto exit_fail;
@@ -602,14 +606,18 @@ PHP_FUNCTION(proc_open)
                                descriptors[ndesc].mode = DESC_FILE;
 
                                if ((zfile = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) {
-                                       convert_to_string_ex(zfile);
+                                       if (!try_convert_to_string(zfile)) {
+                                               goto exit_fail;
+                                       }
                                } else {
                                        php_error_docref(NULL, E_WARNING, "Missing file name parameter for 'file'");
                                        goto exit_fail;
                                }
 
                                if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 2)) != NULL) {
-                                       convert_to_string_ex(zmode);
+                                       if (!try_convert_to_string(zmode)) {
+                                               goto exit_fail;
+                                       }
                                } else {
                                        php_error_docref(NULL, E_WARNING, "Missing mode parameter for 'file'");
                                        goto exit_fail;
index 4fa705bed97b65b91543d6162a4626c4556e39dc..24d8357d7fec02d0247410cf05c2cb37baaa0f34 100644 (file)
@@ -1576,7 +1576,9 @@ PHP_FUNCTION(stream_is_local)
                }
                wrapper = stream->wrapper;
        } else {
-               convert_to_string_ex(zstream);
+               if (!try_convert_to_string(zstream)) {
+                       return;
+               }
 
                wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(zstream), NULL, 0);
        }
index e0141ffaea2fd4b0affd81e997fb700dcf8023fa..a7aa02fcbda0e83db115ddb0863b42523b97fd1e 100644 (file)
@@ -2494,6 +2494,10 @@ PHP_FUNCTION(substr_replace)
                convert_to_long_ex(from);
        }
 
+       if (EG(exception)) {
+               return;
+       }
+
        if (argc > 3) {
                if (Z_TYPE_P(len) != IS_ARRAY) {
                        convert_to_long_ex(len);
@@ -3518,7 +3522,9 @@ PHP_FUNCTION(strtr)
                        php_strtr_array(return_value, str, pats);
                }
        } else {
-               convert_to_string_ex(from);
+               if (!try_convert_to_string(from)) {
+                       return;
+               }
 
                RETURN_STR(php_strtr_ex(str,
                                  Z_STRVAL_P(from),
@@ -4438,6 +4444,10 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
                convert_to_string_ex(replace);
        }
 
+       if (EG(exception)) {
+               return;
+       }
+
        /* if subject is an array */
        if (Z_TYPE_P(subject) == IS_ARRAY) {
                array_init(return_value);
@@ -4840,6 +4850,9 @@ PHP_FUNCTION(setlocale)
                }
 
                loc = zval_get_string(plocale);
+               if (EG(exception)) {
+                       return;
+               }
 
                if (!strcmp("0", ZSTR_VAL(loc))) {
                        zend_string_release_ex(loc, 0);
index 6d89dd0c6c0b312c05cc664ce00038ef91cdfa82..00b0ccb01252d380269a304ed7fe5fa1911060d4 100644 (file)
@@ -34,7 +34,6 @@ $inputs = array(
       'empty string DQ' => "",
       'string DQ' => "string",
       'instance of classWithToString' => new classWithToString(),
-      'instance of classWithoutToString' => new classWithoutToString(),
       'undefined var' => @$undefined_var,
 );
 
@@ -46,14 +45,11 @@ var_dump($inputs);
 --EXPECT--
 *** Testing array_multisort() : usage variation  - test sort order of all types***
 bool(true)
-array(10) {
+array(9) {
   ["uppercase NULL"]=>
   NULL
   ["empty string DQ"]=>
   string(0) ""
-  ["instance of classWithoutToString"]=>
-  object(classWithoutToString)#2 (0) {
-  }
   ["undefined var"]=>
   NULL
   ["float -10.5"]=>
index 16a728e088f7e947551da26f579549b754510b30..dd852ef61f19cb220bae74b61192855fb3818579 100644 (file)
@@ -76,10 +76,9 @@ $values = array(
 // loop through each element of the array for class
 
 foreach($values as $value) {
-      echo "\nArg value $value \n";
+      echo "\nArg value " . (is_object($value) ? get_class($value) : $value) . " \n";
       var_dump( get_class_methods($value) );
 };
-
 echo "Done";
 ?>
 --EXPECTF--
@@ -163,9 +162,8 @@ NULL
 
 Arg value string 
 NULL
-Error: 4096 - Object of class stdClass could not be converted to string, %s(76)
 
-Arg value  
+Arg value stdClass 
 array(0) {
 }
 
index 8dde525ae82e751d8439977565ecfaf9611c7889..0ad57568373766cdbd34d2f7ad9fc601f3a55801 100644 (file)
@@ -77,7 +77,7 @@ $values = array(
 // loop through each element of the array for object
 
 foreach($values as $value) {
-      echo "\nArg value $value \n";
+      echo "\nArg value " . (is_object($value) ? get_class($value) : $value) . " \n";
       var_dump( get_parent_class($value) );
 };
 
@@ -166,9 +166,8 @@ bool(false)
 Arg value String 
 In autoload(String)
 bool(false)
-Error: 4096 - Object of class stdClass could not be converted to string, %s(77)
 
-Arg value  
+Arg value stdClass 
 bool(false)
 
 Arg value  
index 90bfb45f282cac5dfe1a4a030cbdbf1e40727f60..0b460b08d1e7aa43dc5477b6bfb2baf5670d5ce7 100644 (file)
@@ -47,7 +47,11 @@ foreach ($array as $var) {
 
 foreach ($types as $type) {
        foreach ($array as $var) {
-               var_dump(settype($var, $type));
+               try {
+                       var_dump(settype($var, $type));
+               } catch (Error $e) {
+                       echo "Error: ", $e->getMessage(), "\n";
+               }
                var_dump($var);
        }
 }
@@ -344,7 +348,6 @@ bool(true)
 string(14) "Resource id #%d"
 bool(true)
 string(14) "Resource id #%d"
-string(57) "Object of class stdClass could not be converted to string"
-bool(true)
-string(6) "Object"
+Error: Object of class stdClass could not be converted to string
+string(0) ""
 Done
index f27d0a66cf9ea41df893fd61637b39a717bb2be6..96e774b51fc224967a1255cdf1d16df9f3ea2974 100644 (file)
@@ -22,7 +22,11 @@ base_convert(1234, 1, 10);
 base_convert(1234, 10, 37);
 
 echo "Incorrect input\n";
-base_convert(new classA(), 8, 10);
+try {
+    base_convert(new classA(), 8, 10);
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 ?>
 --EXPECTF--
@@ -39,5 +43,4 @@ Warning: base_convert(): Invalid `from base' (1) in %s on line %d
 
 Warning: base_convert(): Invalid `to base' (37) in %s on line %d
 Incorrect input
-
-Recoverable fatal error: Object of class classA could not be converted to string in %s on line %d
+Object of class classA could not be converted to string
index 5cfc9c2ac3cb25ab271f6d9218318e19c773add6..3caffde2329760a63c68bbc13f58c983bfee9a69 100644 (file)
@@ -7,7 +7,11 @@ $arrayLarge = array_fill(0, 113663, '*');
 
 $resourceFileTemp = fopen('php://temp', 'r+');
 stream_context_set_params($resourceFileTemp, array());
-preg_replace('', function() {}, $resourceFileTemp);
+try {
+    preg_replace('', function() {}, $resourceFileTemp);
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 ?>
 --EXPECTF--
-Recoverable fatal error: Object of class Closure could not be converted to string in %s on line %d
+Object of class Closure could not be converted to string
index 37ecfd14d571dc30d83f64df6987bc7c8f036020..4e1ece601649713e8c90634f599ab2aa3bfeb76a 100644 (file)
@@ -29,7 +29,11 @@ var_dump( strval() );
 
 // Testing strval with a object which has no toString() method
 echo "\n-- Testing strval() function with object which has not toString() method  --\n";
-var_dump( strval(new MyClass()) );
+try {
+    var_dump( strval(new MyClass()) );
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 ?>
 ===DONE===
@@ -47,5 +51,5 @@ Warning: strval() expects exactly 1 parameter, 0 given in %s on line %d
 NULL
 
 -- Testing strval() function with object which has not toString() method  --
-
-Recoverable fatal error: Object of class MyClass could not be converted to string in %s on line %d
+Object of class MyClass could not be converted to string
+===DONE===
index ca0273c213e4855016aaa2688c7b3d6cf300af07..410c0fdeb94f9cb734ad07972f0dd5623d4f8251 100644 (file)
@@ -1222,6 +1222,13 @@ PHP_FUNCTION(unserialize)
                                zend_hash_add_empty_element(class_hash, lcname);
                        zend_string_release_ex(lcname, 0);
                        } ZEND_HASH_FOREACH_END();
+
+                       /* Exception during string conversion. */
+                       if (EG(exception)) {
+                               zend_hash_destroy(class_hash);
+                               FREE_HASHTABLE(class_hash);
+                               PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+                       }
                }
                php_var_unserialize_set_allowed_classes(var_hash, class_hash);
        }
index f60f08bd57f3c0f455ecd90a65facc666638f127..fb60883226b33e8463c17ef81fce4d51a0fca138 100644 (file)
@@ -1629,7 +1629,10 @@ PHP_FUNCTION(xml_parser_set_option)
                        break;
                case PHP_XML_OPTION_TARGET_ENCODING: {
                        const xml_encoding *enc;
-                       convert_to_string_ex(val);
+                       if (!try_convert_to_string(val)) {
+                               return;
+                       }
+
                        enc = xml_get_encoding((XML_Char*)Z_STRVAL_P(val));
                        if (enc == NULL) {
                                php_error_docref(NULL, E_WARNING, "Unsupported target encoding \"%s\"", Z_STRVAL_P(val));
index 3ce3fed0e13fc9ea4fb7b3487674db828d5c7b14..b3b202af39b51bb357645b7ddc1b41bd836910c3 100644 (file)
@@ -124,6 +124,9 @@ zval *xmlreader_get_property_ptr_ptr(zval *object, zval *member, int type, void
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return NULL;
+               }
        }
 
        obj = Z_XMLREADER_P(object);
@@ -155,6 +158,9 @@ zval *xmlreader_read_property(zval *object, zval *member, int type, void **cache
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return &EG(uninitialized_zval);
+               }
        }
 
        obj = Z_XMLREADER_P(object);
@@ -190,6 +196,9 @@ zval *xmlreader_write_property(zval *object, zval *member, zval *value, void **c
        if (Z_TYPE_P(member) != IS_STRING) {
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
+               if (EG(exception)) {
+                       return value;
+               }
        }
 
        obj = Z_XMLREADER_P(object);
index 8d9ff876119fc4551600dd752cad2f54c8c16150..51dc647b195f2f452065dc15f48db9c209f74040 100644 (file)
@@ -522,7 +522,9 @@ static XMLRPC_VALUE PHP_to_XMLRPC_worker (const char* key, zval* in_val, int dep
                                        }
                                        break;
                                case xmlrpc_datetime:
-                                       convert_to_string(&val);
+                                       if (!try_convert_to_string(&val)) {
+                                               return NULL;
+                                       }
                                        xReturn = XMLRPC_CreateValueDateTime_ISO8601(key, Z_STRVAL(val));
                                        break;
                                case xmlrpc_boolean:
@@ -538,7 +540,9 @@ static XMLRPC_VALUE PHP_to_XMLRPC_worker (const char* key, zval* in_val, int dep
                                        xReturn = XMLRPC_CreateValueDouble(key, Z_DVAL(val));
                                        break;
                                case xmlrpc_string:
-                                       convert_to_string(&val);
+                                       if (!try_convert_to_string(&val)) {
+                                               return NULL;
+                                       }
                                        xReturn = XMLRPC_CreateValueString(key, Z_STRVAL(val), Z_STRLEN(val));
                                        break;
                                case xmlrpc_vector:
@@ -925,7 +929,10 @@ static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data)
                                STRUCT_XMLRPC_ERROR err = {0};
 
                                /* return value should be a string */
-                               convert_to_string(&retval);
+                               if (!try_convert_to_string(&retval)) {
+                                       zend_string_release_ex(php_function_name, 0);
+                                       break;
+                               }
 
                                xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
 
index 18443f9efa8fbfb4bc572b254808ea0198b44f8d..919006041a9fbd387fe2100ab5d6065e3b0925ce 100644 (file)
@@ -150,7 +150,10 @@ static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params)
                        return NULL;
                } else {
                        if (Z_TYPE_P(value) != IS_STRING) {
-                               convert_to_string(value);
+                               if (!try_convert_to_string(value)) {
+                                       efree(params);
+                                       return NULL;
+                               }
                        }
 
                        if (!xpath_params) {
@@ -753,13 +756,16 @@ PHP_FUNCTION(xsl_xsltprocessor_set_parameter)
        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "sa", &namespace, &namespace_len, &array_value) == SUCCESS) {
                intern = Z_XSL_P(id);
                ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(array_value), string_key, entry) {
+                       zval tmp;
                        if (string_key == NULL) {
                                php_error_docref(NULL, E_WARNING, "Invalid parameter array");
                                RETURN_FALSE;
                        }
-                       convert_to_string_ex(entry);
-                       Z_TRY_ADDREF_P(entry);
-                       zend_hash_update(intern->parameter, string_key, entry);
+                       ZVAL_STR(&tmp, zval_get_string(entry));
+                       if (EG(exception)) {
+                               return;
+                       }
+                       zend_hash_update(intern->parameter, string_key, &tmp);
                } ZEND_HASH_FOREACH_END();
                RETURN_TRUE;
        } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "sSS", &namespace, &namespace_len, &name, &value) == SUCCESS) {
@@ -841,9 +847,13 @@ PHP_FUNCTION(xsl_xsltprocessor_register_php_functions)
                intern = Z_XSL_P(id);
 
                ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array_value), entry) {
-                       convert_to_string_ex(entry);
-                       ZVAL_LONG(&new_string ,1);
-                       zend_hash_update(intern->registered_phpfunctions, Z_STR_P(entry), &new_string);
+                       zend_string *str = zval_get_string(entry);
+                       if (EG(exception)) {
+                               return;
+                       }
+                       ZVAL_LONG(&new_string, 1);
+                       zend_hash_update(intern->registered_phpfunctions, str, &new_string);
+                       zend_string_release(str);
                } ZEND_HASH_FOREACH_END();
 
                intern->registerPhpFunctions = 2;
index df3eade9956cb40f4f2603010023ef3d204fa8bd..c2b41309c0da446b0a0c49e63659f22953f55e11 100644 (file)
@@ -876,6 +876,9 @@ static zval *php_zip_get_property_ptr_ptr(zval *object, zval *member, int type,
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return NULL;
+               }
        }
 
        obj = Z_ZIP_P(object);
@@ -907,6 +910,9 @@ static zval *php_zip_read_property(zval *object, zval *member, int type, void **
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return &EG(uninitialized_zval);
+               }
        }
 
        obj = Z_ZIP_P(object);
@@ -943,6 +949,9 @@ static int php_zip_has_property(zval *object, zval *member, int type, void **cac
                ZVAL_STR(&tmp_member, zval_get_string_func(member));
                member = &tmp_member;
                cache_slot = NULL;
+               if (EG(exception)) {
+                       return 0;
+               }
        }
 
        obj = Z_ZIP_P(object);
index f3bda6398f46aa27781bcdb6377c9fa154b9ba81..9060dcb2e2ed7e35677a5b00c2fe524e7f9b44a9 100644 (file)
@@ -777,7 +777,7 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict,
                                                size_t i;
 
                                                *++ptr = zval_get_string(cur);
-                                               if (!*ptr || ZSTR_LEN(*ptr) == 0) {
+                                               if (!*ptr || ZSTR_LEN(*ptr) == 0 || EG(exception)) {
                                                        if (*ptr) {
                                                                efree(*ptr);
                                                        }
@@ -785,7 +785,9 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict,
                                                                efree(ptr);
                                                        }
                                                        efree(strings);
-                                                       php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
+                                                       if (!EG(exception)) {
+                                                               php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
+                                                       }
                                                        return 0;
                                                }
                                                for (i = 0; i < ZSTR_LEN(*ptr); i++) {
index 73b71863a4d25da18a4ebb293753f9d6a0e7f170..bdd9b1b48e9386ed7fe223443d0a6389833aa4dd 100644 (file)
@@ -669,7 +669,10 @@ static size_t php_userstreamop_read(php_stream *stream, char *buf, size_t count)
        }
 
        if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
-               convert_to_string(&retval);
+               if (!try_convert_to_string(&retval)) {
+                       return -1;
+               }
+
                didread = Z_STRLEN(retval);
                if (didread > count) {
                        php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_READ " - read " ZEND_LONG_FMT " bytes more data than requested (" ZEND_LONG_FMT " read, " ZEND_LONG_FMT " max) - excess data will be lost",
index 53144ca207177eead3a197d38e58621414b09006..418aa1fc257e6bed2e5777a610c2cda92fa691d3 100644 (file)
@@ -3,12 +3,6 @@ ZE2 __toString()
 --FILE--
 <?php
 
-function my_error_handler($errno, $errstr, $errfile, $errline) {
-       var_dump($errstr);
-}
-
-set_error_handler('my_error_handler');
-
 class test1
 {
 }
@@ -33,7 +27,11 @@ class test3
 echo "====test1====\n";
 $o = new test1;
 print_r($o);
-var_dump((string)$o);
+try {
+    var_dump((string)$o);
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 var_dump($o);
 
 echo "====test2====\n";
@@ -70,7 +68,11 @@ echo sprintf("%s", $o);
 echo "====test10====\n";
 $o = new test3;
 var_dump($o);
-echo $o;
+try {
+    echo $o;
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 ?>
 ====DONE====
@@ -79,9 +81,8 @@ echo $o;
 test1 Object
 (
 )
-string(54) "Object of class test1 could not be converted to string"
-string(0) ""
-object(test1)#%d (0) {
+Object of class test1 could not be converted to string
+object(test1)#1 (0) {
 }
 ====test2====
 test2 Object
@@ -89,7 +90,7 @@ test2 Object
 )
 test2::__toString()
 Converted
-object(test2)#%d (0) {
+object(test2)#3 (0) {
 }
 ====test3====
 test2::__toString()
@@ -113,7 +114,8 @@ test2::__toString()
 Converted
 ====test7====
 test2::__toString()
-string(19) "Illegal offset type"
+
+Warning: Illegal offset type in %s on line %d
 ====test8====
 test2::__toString()
 string(9) "Converted"
@@ -123,8 +125,8 @@ string(9) "Converted"
 test2::__toString()
 Converted
 ====test10====
-object(test3)#%d (0) {
+object(test3)#1 (0) {
 }
 test3::__toString()
-string(53) "Method test3::__toString() must return a string value"
+Method test3::__toString() must return a string value
 ====DONE====
index e3bc7f8f2c082845d24149e4f1e5173ea7355573..4dad51f2cf5e945d44a3b0cb2bd16fdaca4f90eb 100644 (file)
@@ -29,5 +29,6 @@ catch(Exception $e)
 
 ?>
 ====DONE====
---EXPECTF--
-Fatal error: Method Test::__toString() must not throw an exception, caught Exception: Damn! in %stostring_003.php on line %d
+--EXPECT--
+string(5) "Damn!"
+====DONE====
index 907f7bc306c527896f6afb99e1db23810a5b61c8..4134c702b67c132a4ac7855eb72b75fd3fb475ab 100644 (file)
@@ -12,12 +12,19 @@ error_reporting(8191);
 echo "Object with no __toString():\n";
 $obj = new stdClass;
 echo "Try 1:\n";
-printf($obj);
+try {
+    printf($obj);
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 printf("\n");
 
 echo "\nTry 2:\n";
-printf($obj . "\n");
-
+try {
+    printf($obj . "\n");
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 echo "\n\nObject with bad __toString():\n";
 class badToString {
@@ -25,30 +32,38 @@ class badToString {
                return 0;
        }
 }
+
 $obj = new badToString;
 echo "Try 1:\n";
-printf($obj);
+try {
+    printf($obj);
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 printf("\n");
 
 echo "\nTry 2:\n";
-printf($obj . "\n");
+try {
+    printf($obj . "\n");
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
 
 ?>
 --EXPECT--
 Object with no __toString():
 Try 1:
-Error: 4096 - Object of class stdClass could not be converted to string
-Object
+Object of class stdClass could not be converted to string
 
-Try 2:
-Error: 4096 - Object of class stdClass could not be converted to string
 
+Try 2:
+Object of class stdClass could not be converted to string
 
 
 Object with bad __toString():
 Try 1:
-Error: 4096 - Method badToString::__toString() must return a string value
+Method badToString::__toString() must return a string value
 
 
 Try 2:
-Error: 4096 - Method badToString::__toString() must return a string value
+Method badToString::__toString() must return a string value
index 86a4c330076d06ca35f6d9275c9e6d9f04198414..48f60595b426a9d536c3a58d5b95774f080db328 100644 (file)
@@ -657,7 +657,9 @@ PHP_FUNCTION(sapi_windows_cp_conv)
                        RETURN_NULL();
                }
        } else {
-               convert_to_string(z_in_cp);
+               if (!try_convert_to_string(z_in_cp)) {
+                       return;
+               }
 
                in_cp = php_win32_cp_get_by_enc(Z_STRVAL_P(z_in_cp));
                if (!in_cp) {
@@ -678,7 +680,9 @@ PHP_FUNCTION(sapi_windows_cp_conv)
                        RETURN_NULL();
                }
        } else {
-               convert_to_string(z_out_cp);
+               if (!try_convert_to_string(z_out_cp)) {
+                       return;
+               }
 
                out_cp = php_win32_cp_get_by_enc(Z_STRVAL_P(z_out_cp));
                if (!out_cp) {