summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-02-26 15:32:18 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-06-05 14:25:07 +0200
commita31f46421d7bf6f55dd9ac5876b8e2eacf7e0708 (patch)
tree24ffd7c5ae5e321c3994048fdd0fd9f68ae7457c /ext
parent528aa7932a839fc6319979c34aa372805d8dc41c (diff)
downloadphp-git-a31f46421d7bf6f55dd9ac5876b8e2eacf7e0708.tar.gz
Allow exceptions in __toString()
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.
Diffstat (limited to 'ext')
-rw-r--r--ext/date/php_date.c12
-rw-r--r--ext/dba/dba.c6
-rw-r--r--ext/dom/attr.c7
-rw-r--r--ext/dom/characterdata.c3
-rw-r--r--ext/dom/document.c17
-rw-r--r--ext/dom/node.c25
-rw-r--r--ext/dom/processinginstruction.c3
-rw-r--r--ext/dom/tests/toString_exceptions.phpt56
-rw-r--r--ext/exif/exif.c8
-rw-r--r--ext/gd/gd.c5
-rw-r--r--ext/iconv/iconv.c13
-rw-r--r--ext/imap/php_imap.c12
-rw-r--r--ext/intl/dateformat/dateformat_format_object.cpp4
-rw-r--r--ext/intl/timezone/timezone_class.cpp5
-rw-r--r--ext/intl/timezone/timezone_methods.cpp4
-rw-r--r--ext/intl/transliterator/transliterator_class.c9
-rw-r--r--ext/intl/transliterator/transliterator_methods.c5
-rw-r--r--ext/libxml/libxml.c5
-rw-r--r--ext/mbstring/mbstring.c43
-rw-r--r--ext/mbstring/php_mbregex.c4
-rw-r--r--ext/mysqli/mysqli.c6
-rw-r--r--ext/mysqli/mysqli_api.c9
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c5
-rw-r--r--ext/oci8/oci8_statement.c43
-rw-r--r--ext/odbc/php_odbc.c4
-rw-r--r--ext/openssl/openssl.c82
-rw-r--r--ext/openssl/tests/bug38261.phpt9
-rw-r--r--ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt10
-rw-r--r--ext/openssl/xp_ssl.c40
-rw-r--r--ext/pcntl/pcntl.c21
-rw-r--r--ext/pcre/php_pcre.c5
-rw-r--r--ext/pcre/tests/preg_replace_error1.phpt9
-rw-r--r--ext/pcre/tests/preg_replace_error2.phpt10
-rw-r--r--ext/pdo/pdo_sql_parser.re3
-rw-r--r--ext/pdo/pdo_stmt.c25
-rw-r--r--ext/pdo/php_pdo_driver.h2
-rw-r--r--ext/pdo_firebird/firebird_driver.c9
-rw-r--r--ext/pdo_firebird/firebird_statement.c4
-rw-r--r--ext/pdo_oci/oci_driver.c12
-rw-r--r--ext/pdo_oci/oci_statement.c7
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c5
-rw-r--r--ext/pdo_sqlite/sqlite_driver.c5
-rw-r--r--ext/pdo_sqlite/sqlite_statement.c8
-rw-r--r--ext/pdo_sqlite/tests/pdo_sqlite_tostring_exception.phpt45
-rw-r--r--ext/pgsql/pgsql.c64
-rw-r--r--ext/readline/readline.c16
-rw-r--r--ext/reflection/php_reflection.c73
-rw-r--r--ext/reflection/tests/bug74673.phpt7
-rw-r--r--ext/session/session.c48
-rw-r--r--ext/simplexml/simplexml.c19
-rw-r--r--ext/snmp/snmp.c6
-rw-r--r--ext/sockets/conversions.c5
-rw-r--r--ext/spl/spl_iterators.c35
-rw-r--r--ext/spl/tests/iterator_036.phpt7
-rw-r--r--ext/spl/tests/recursive_tree_iterator_007.phpt6
-rw-r--r--ext/sqlite3/sqlite3.c27
-rw-r--r--ext/sqlite3/tests/exception_from_toString.phpt39
-rw-r--r--ext/standard/array.c9
-rw-r--r--ext/standard/assert.c22
-rw-r--r--ext/standard/basic_functions.c5
-rw-r--r--ext/standard/filters.c11
-rw-r--r--ext/standard/formatted_print.c5
-rw-r--r--ext/standard/head.c20
-rw-r--r--ext/standard/math.c5
-rw-r--r--ext/standard/pack.c7
-rw-r--r--ext/standard/password.c3
-rw-r--r--ext/standard/proc_open.c16
-rw-r--r--ext/standard/streamsfuncs.c4
-rw-r--r--ext/standard/string.c15
-rw-r--r--ext/standard/tests/array/array_multisort_variation8.phpt6
-rw-r--r--ext/standard/tests/class_object/get_class_methods_variation_001.phpt6
-rw-r--r--ext/standard/tests/class_object/get_parent_class_variation_002.phpt5
-rw-r--r--ext/standard/tests/general_functions/type.phpt11
-rw-r--r--ext/standard/tests/math/base_convert_error.phpt9
-rw-r--r--ext/standard/tests/streams/bug61115.phpt8
-rw-r--r--ext/standard/tests/strings/strval_error.phpt10
-rw-r--r--ext/standard/var.c7
-rw-r--r--ext/xml/xml.c5
-rw-r--r--ext/xmlreader/php_xmlreader.c9
-rw-r--r--ext/xmlrpc/xmlrpc-epi-php.c13
-rw-r--r--ext/xsl/xsltprocessor.c24
-rw-r--r--ext/zip/php_zip.c9
-rw-r--r--ext/zlib/zlib.c6
83 files changed, 913 insertions, 313 deletions
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index f7db8a26d7..3e8fb419d8 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -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 ||
diff --git a/ext/dba/dba.c b/ext/dba/dba.c
index ede12f0bd6..952993582b 100644
--- a/ext/dba/dba.c
+++ b/ext/dba/dba.c
@@ -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;
diff --git a/ext/dom/attr.c b/ext/dom/attr.c
index f59b46799f..0255708517 100644
--- a/ext/dom/attr.c
+++ b/ext/dom/attr.c
@@ -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);
diff --git a/ext/dom/characterdata.c b/ext/dom/characterdata.c
index f473240498..7676370677 100644
--- a/ext/dom/characterdata.c
+++ b/ext/dom/characterdata.c
@@ -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);
diff --git a/ext/dom/document.c b/ext/dom/document.c
index 95b077b648..235323e1d7 100644
--- a/ext/dom/document.c
+++ b/ext/dom/document.c
@@ -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);
diff --git a/ext/dom/node.c b/ext/dom/node.c
index 03e61efa67..44e6f58b30 100644
--- a/ext/dom/node.c
+++ b/ext/dom/node.c
@@ -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));
diff --git a/ext/dom/processinginstruction.c b/ext/dom/processinginstruction.c
index 0487abc373..103bfd74f0 100644
--- a/ext/dom/processinginstruction.c
+++ b/ext/dom/processinginstruction.c
@@ -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
index 0000000000..e59532d48c
--- /dev/null
+++ b/ext/dom/tests/toString_exceptions.phpt
@@ -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>
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index 1fd42fe096..0ec5b1a1b8 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -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");
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 786589d263..9aa3953918 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -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;
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index bb40b6a215..688e3a2552 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -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);
diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c
index 3cee4e023e..b5f12f6eee 100644
--- a/ext/imap/php_imap.c
+++ b/ext/imap/php_imap.c
@@ -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;
}
diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp
index c2429fb592..90e148bca0 100644
--- a/ext/intl/dateformat/dateformat_format_object.cpp
+++ b/ext/intl/dateformat/dateformat_format_object.cpp
@@ -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);
diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp
index aabb0f3f55..695cc7d3ea 100644
--- a/ext/intl/timezone/timezone_class.cpp
+++ b/ext/intl/timezone/timezone_class.cpp
@@ -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 "
diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp
index 3f91db3130..6e1d22324b 100644
--- a/ext/intl/timezone/timezone_methods.cpp
+++ b/ext/intl/timezone/timezone_methods.cpp
@@ -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);
diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c
index a662dcee7d..a619ed4309 100644
--- a/ext/intl/transliterator/transliterator_class.c
+++ b/ext/intl/transliterator/transliterator_class.c
@@ -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);
diff --git a/ext/intl/transliterator/transliterator_methods.c b/ext/intl/transliterator/transliterator_methods.c
index 25d0b9a4da..50dd344671 100644
--- a/ext/intl/transliterator/transliterator_methods.c
+++ b/ext/intl/transliterator/transliterator_methods.c
@@ -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 ),
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 7471065494..15ef274ee4 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -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 */
}
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index 69d5fa9101..e3611562e5 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -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;
}
diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c
index 83cd25d89d..9fac8233ba 100644
--- a/ext/mbstring/php_mbregex.c
+++ b/ext/mbstring/php_mbregex.c
@@ -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 */
}
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 394a838512..9964ea0be4 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -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);
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 1a7303c987..13d21e9312 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -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);
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index 641c7ee783..7da46a90f8 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -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;
}
diff --git a/ext/oci8/oci8_statement.c b/ext/oci8/oci8_statement.c
index 4face29e4a..91f6223373 100644
--- a/ext/oci8/oci8_statement.c
+++ b/ext/oci8/oci8_statement.c
@@ -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 */
diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
index 37257c3e12..6bd24781b4 100644
--- a/ext/odbc/php_odbc.c
+++ b/ext/odbc/php_odbc.c
@@ -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) {
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 8cf294b361..7f287c8823 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -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();
}
diff --git a/ext/openssl/tests/bug38261.phpt b/ext/openssl/tests/bug38261.phpt
index fa25d93d62..e6e345d5ea 100644
--- a/ext/openssl/tests/bug38261.phpt
+++ b/ext/openssl/tests/bug38261.phpt
@@ -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
diff --git a/ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt b/ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt
index f892c6854f..63dabe8f32 100644
--- a/ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt
+++ b/ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt
@@ -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"
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index d5276cd5b9..ad08e1f13a 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -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);
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index 63751d4b17..300de1e7d4 100644
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -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;
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index 05f8d9f817..46794fe1d1 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -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;
diff --git a/ext/pcre/tests/preg_replace_error1.phpt b/ext/pcre/tests/preg_replace_error1.phpt
index 8e20108b88..780556956a 100644
--- a/ext/pcre/tests/preg_replace_error1.phpt
+++ b/ext/pcre/tests/preg_replace_error1.phpt
@@ -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
diff --git a/ext/pcre/tests/preg_replace_error2.phpt b/ext/pcre/tests/preg_replace_error2.phpt
index 8c826587ea..a334b2fefd 100644
--- a/ext/pcre/tests/preg_replace_error2.phpt
+++ b/ext/pcre/tests/preg_replace_error2.phpt
@@ -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
diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re
index 5950cdc38e..b04e2fb928 100644
--- a/ext/pdo/pdo_sql_parser.re
+++ b/ext/pdo/pdo_sql_parser.re
@@ -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 */
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index 92e594c76b..bd93ca3cb2 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -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
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index d17b168c2d..d057857fa6 100644
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -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;
}
diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c
index 6c83717e65..a4ff7e5c5a 100644
--- a/ext/pdo_firebird/firebird_driver.c
+++ b/ext/pdo_firebird/firebird_driver.c
@@ -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);
}
diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c
index af71007b56..aee748d0e1 100644
--- a/ext/pdo_firebird/firebird_statement.c
+++ b/ext/pdo_firebird/firebird_statement.c
@@ -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);
diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c
index 607069008d..f121b4791b 100644
--- a/ext/pdo_oci/oci_driver.c
+++ b/ext/pdo_oci/oci_driver.c
@@ -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),
diff --git a/ext/pdo_oci/oci_statement.c b/ext/pdo_oci/oci_statement.c
index 79733c2c57..b983f20116 100644
--- a/ext/pdo_oci/oci_statement.c
+++ b/ext/pdo_oci/oci_statement.c
@@ -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;
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index e8b748a36f..5aae5d0a38 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -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);
diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c
index 02342e9fe4..9e86a82323 100644
--- a/ext/pdo_sqlite/sqlite_driver.c
+++ b/ext/pdo_sqlite/sqlite_driver.c
@@ -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;
}
diff --git a/ext/pdo_sqlite/sqlite_statement.c b/ext/pdo_sqlite/sqlite_statement.c
index 186bf182b1..d8a68efb05 100644
--- a/ext/pdo_sqlite/sqlite_statement.c
+++ b/ext/pdo_sqlite/sqlite_statement.c
@@ -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
index 0000000000..b1cd78eee7
--- /dev/null
+++ b/ext/pdo_sqlite/tests/pdo_sqlite_tostring_exception.phpt
@@ -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 ...
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index 1be592a319..9dd08f249a 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -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:
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index b66928ebd6..9c018bf9c8 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -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));
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index e6ca3322cb..4623efb3cf 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -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));
diff --git a/ext/reflection/tests/bug74673.phpt b/ext/reflection/tests/bug74673.phpt
index 8e4e8e3a18..47f7604e8b 100644
--- a/ext/reflection/tests/bug74673.phpt
+++ b/ext/reflection/tests/bug74673.phpt
@@ -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
diff --git a/ext/session/session.c b/ext/session/session.c
index bf3ddee0d5..671968e8da 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -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);
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index fb55b6b195..01c119888e 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -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);
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index 34e951b6ec..69ff9b00f4 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -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);
diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c
index a9f287a8ea..f24e0926ce 100644
--- a/ext/sockets/conversions.c
+++ b/ext/sockets/conversions.c
@@ -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:
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 697d5f1d91..defb9fdb88 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -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) {
diff --git a/ext/spl/tests/iterator_036.phpt b/ext/spl/tests/iterator_036.phpt
index 74d393b677..07a1f79134 100644
--- a/ext/spl/tests/iterator_036.phpt
+++ b/ext/spl/tests/iterator_036.phpt
@@ -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
diff --git a/ext/spl/tests/recursive_tree_iterator_007.phpt b/ext/spl/tests/recursive_tree_iterator_007.phpt
index 7374a066fa..a017254df0 100644
--- a/ext/spl/tests/recursive_tree_iterator_007.phpt
+++ b/ext/spl/tests/recursive_tree_iterator_007.phpt
@@ -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===
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index b993d622ff..c3ffeabc00 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -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
index 0000000000..1d6ed39f2a
--- /dev/null
+++ b/ext/sqlite3/tests/exception_from_toString.phpt
@@ -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 ...
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 5448a1815d..71a7cf17e7 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -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;
diff --git a/ext/standard/assert.c b/ext/standard/assert.c
index eb1b59db74..6e21af6dd5 100644
--- a/ext/standard/assert.c
+++ b/ext/standard/assert.c
@@ -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);
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 920974fe48..8d4dec48c1 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -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();
diff --git a/ext/standard/filters.c b/ext/standard/filters.c
index 9d90558f59..83fcf2dcbf 100644
--- a/ext/standard/filters.c
+++ b/ext/standard/filters.c
@@ -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 {
diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c
index b804cda500..4ee68adefa 100644
--- a/ext/standard/formatted_print.c
+++ b/ext/standard/formatted_print.c
@@ -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);
diff --git a/ext/standard/head.c b/ext/standard/head.c
index e8b5d5b171..f1b2fa4e8b 100644
--- a/ext/standard/head.c
+++ b/ext/standard/head.c
@@ -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) {
diff --git a/ext/standard/math.c b/ext/standard/math.c
index cefcd38769..840df9103e 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -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);
diff --git a/ext/standard/pack.c b/ext/standard/pack.c
index 5f375585d4..3c0dc009f1 100644
--- a/ext/standard/pack.c
+++ b/ext/standard/pack.c
@@ -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:
diff --git a/ext/standard/password.c b/ext/standard/password.c
index 3f1ff6dd55..52ff1518e6 100644
--- a/ext/standard/password.c
+++ b/ext/standard/password.c
@@ -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:
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index 326cfc1431..d76e1595f3 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -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;
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index 4fa705bed9..24d8357d7f 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -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);
}
diff --git a/ext/standard/string.c b/ext/standard/string.c
index e0141ffaea..a7aa02fcbd 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -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);
diff --git a/ext/standard/tests/array/array_multisort_variation8.phpt b/ext/standard/tests/array/array_multisort_variation8.phpt
index 6d89dd0c6c..00b0ccb012 100644
--- a/ext/standard/tests/array/array_multisort_variation8.phpt
+++ b/ext/standard/tests/array/array_multisort_variation8.phpt
@@ -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"]=>
diff --git a/ext/standard/tests/class_object/get_class_methods_variation_001.phpt b/ext/standard/tests/class_object/get_class_methods_variation_001.phpt
index 16a728e088..dd852ef61f 100644
--- a/ext/standard/tests/class_object/get_class_methods_variation_001.phpt
+++ b/ext/standard/tests/class_object/get_class_methods_variation_001.phpt
@@ -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) {
}
diff --git a/ext/standard/tests/class_object/get_parent_class_variation_002.phpt b/ext/standard/tests/class_object/get_parent_class_variation_002.phpt
index 8dde525ae8..0ad5756837 100644
--- a/ext/standard/tests/class_object/get_parent_class_variation_002.phpt
+++ b/ext/standard/tests/class_object/get_parent_class_variation_002.phpt
@@ -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
diff --git a/ext/standard/tests/general_functions/type.phpt b/ext/standard/tests/general_functions/type.phpt
index 90bfb45f28..0b460b08d1 100644
--- a/ext/standard/tests/general_functions/type.phpt
+++ b/ext/standard/tests/general_functions/type.phpt
@@ -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
diff --git a/ext/standard/tests/math/base_convert_error.phpt b/ext/standard/tests/math/base_convert_error.phpt
index f27d0a66cf..96e774b51f 100644
--- a/ext/standard/tests/math/base_convert_error.phpt
+++ b/ext/standard/tests/math/base_convert_error.phpt
@@ -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
diff --git a/ext/standard/tests/streams/bug61115.phpt b/ext/standard/tests/streams/bug61115.phpt
index 5cfc9c2ac3..3caffde232 100644
--- a/ext/standard/tests/streams/bug61115.phpt
+++ b/ext/standard/tests/streams/bug61115.phpt
@@ -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
diff --git a/ext/standard/tests/strings/strval_error.phpt b/ext/standard/tests/strings/strval_error.phpt
index 37ecfd14d5..4e1ece6016 100644
--- a/ext/standard/tests/strings/strval_error.phpt
+++ b/ext/standard/tests/strings/strval_error.phpt
@@ -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===
diff --git a/ext/standard/var.c b/ext/standard/var.c
index ca0273c213..410c0fdeb9 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -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);
}
diff --git a/ext/xml/xml.c b/ext/xml/xml.c
index f60f08bd57..fb60883226 100644
--- a/ext/xml/xml.c
+++ b/ext/xml/xml.c
@@ -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));
diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c
index 3ce3fed0e1..b3b202af39 100644
--- a/ext/xmlreader/php_xmlreader.c
+++ b/ext/xmlreader/php_xmlreader.c
@@ -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);
diff --git a/ext/xmlrpc/xmlrpc-epi-php.c b/ext/xmlrpc/xmlrpc-epi-php.c
index 8d9ff87611..51dc647b19 100644
--- a/ext/xmlrpc/xmlrpc-epi-php.c
+++ b/ext/xmlrpc/xmlrpc-epi-php.c
@@ -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);
diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
index 18443f9efa..919006041a 100644
--- a/ext/xsl/xsltprocessor.c
+++ b/ext/xsl/xsltprocessor.c
@@ -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;
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index df3eade995..c2b41309c0 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -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);
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index f3bda6398f..9060dcb2e2 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -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++) {