summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/com_dotnet/com_handlers.c3
-rw-r--r--ext/com_dotnet/com_saproxy.c2
-rw-r--r--ext/curl/multi.c11
-rw-r--r--ext/date/php_date.c19
-rw-r--r--ext/date/tests/DateInterval_write_property_return.phpt14
-rw-r--r--ext/dom/php_dom.c6
-rw-r--r--ext/enchant/enchant.c8
-rw-r--r--ext/exif/exif.c15
-rw-r--r--ext/ftp/php_ftp.c6
-rw-r--r--ext/intl/formatter/formatter_parse.c24
-rw-r--r--ext/intl/idn/idn.c8
-rw-r--r--ext/intl/transliterator/transliterator_class.c7
-rw-r--r--ext/ldap/ldap.c93
-rw-r--r--ext/mbstring/mbstring.c9
-rw-r--r--ext/mbstring/php_mbregex.c8
-rw-r--r--ext/mysqli/mysqli.c6
-rw-r--r--ext/mysqli/mysqli_api.c28
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c43
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h1
-rw-r--r--ext/oci8/oci8_interface.c19
-rw-r--r--ext/odbc/php_odbc.c9
-rw-r--r--ext/opcache/Optimizer/compact_literals.c112
-rw-r--r--ext/opcache/Optimizer/dce.c3
-rw-r--r--ext/opcache/Optimizer/escape_analysis.c6
-rw-r--r--ext/opcache/Optimizer/sccp.c11
-rw-r--r--ext/opcache/Optimizer/zend_dfg.c9
-rw-r--r--ext/opcache/Optimizer/zend_dump.c14
-rw-r--r--ext/opcache/Optimizer/zend_inference.c266
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c68
-rw-r--r--ext/opcache/Optimizer/zend_ssa.c16
-rw-r--r--ext/opcache/tests/opt/prop_types.phpt115
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c18
-rw-r--r--ext/opcache/zend_file_cache.c44
-rw-r--r--ext/opcache/zend_persist.c34
-rw-r--r--ext/opcache/zend_persist_calc.c20
-rw-r--r--ext/openssl/openssl.c113
-rw-r--r--ext/pcntl/pcntl.c50
-rw-r--r--ext/pcre/php_pcre.c23
-rw-r--r--ext/pdo/pdo_stmt.c8
-rw-r--r--ext/reflection/php_reflection.c125
-rw-r--r--ext/reflection/tests/ReflectionClass_setStaticPropertyValue_002.phpt2
-rw-r--r--ext/reflection/tests/ReflectionClass_setStaticPropertyValue_003.phpt39
-rw-r--r--ext/reflection/tests/ReflectionProperty_isInitialized.phpt113
-rw-r--r--ext/reflection/tests/ReflectionProperty_typed_static.phpt51
-rw-r--r--ext/reflection/tests/ReflectionType_001.phpt37
-rw-r--r--ext/simplexml/simplexml.c29
-rw-r--r--ext/snmp/snmp.c6
-rw-r--r--ext/soap/soap.c14
-rw-r--r--ext/sockets/sockets.c85
-rw-r--r--ext/spl/spl_array.c6
-rw-r--r--ext/spl/tests/iterator_035.phpt2
-rw-r--r--ext/standard/array.c48
-rw-r--r--ext/standard/basic_functions.c7
-rw-r--r--ext/standard/dns.c32
-rw-r--r--ext/standard/dns_win32.c29
-rw-r--r--ext/standard/exec.c22
-rw-r--r--ext/standard/file.c7
-rw-r--r--ext/standard/fsock.c36
-rw-r--r--ext/standard/head.c12
-rw-r--r--ext/standard/image.c8
-rw-r--r--ext/standard/incomplete_class.c3
-rw-r--r--ext/standard/proc_open.c10
-rw-r--r--ext/standard/scanf.c32
-rw-r--r--ext/standard/streamsfuncs.c55
-rw-r--r--ext/standard/string.c25
-rw-r--r--ext/standard/tests/array/extract_typed_ref.phpt23
-rw-r--r--ext/standard/tests/general_functions/settype_typed_property.phpt28
-rw-r--r--ext/standard/tests/serialize/typed_property_refs.phpt73
-rw-r--r--ext/standard/type.c35
-rw-r--r--ext/standard/var.c59
-rw-r--r--ext/standard/var_unserializer.re68
-rw-r--r--ext/sysvmsg/sysvmsg.c37
-rw-r--r--ext/xml/xml.c14
-rw-r--r--ext/xmlreader/php_xmlreader.c6
-rw-r--r--ext/xmlrpc/xmlrpc-epi-php.c16
-rw-r--r--ext/zend_test/test.c31
-rw-r--r--ext/zip/php_zip.c16
77 files changed, 1798 insertions, 712 deletions
diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c
index 9c58732e0b..fd70a98ef7 100644
--- a/ext/com_dotnet/com_handlers.c
+++ b/ext/com_dotnet/com_handlers.c
@@ -58,7 +58,7 @@ static zval *com_property_read(zval *object, zval *member, int type, void **cahc
return rv;
}
-static void com_property_write(zval *object, zval *member, zval *value, void **cache_slot)
+static zval *com_property_write(zval *object, zval *member, zval *value, void **cache_slot)
{
php_com_dotnet_object *obj;
VARIANT v;
@@ -76,6 +76,7 @@ static void com_property_write(zval *object, zval *member, zval *value, void **c
} else {
php_com_throw_exception(E_INVALIDARG, "this variant has no properties");
}
+ return value;
}
static zval *com_read_dimension(zval *object, zval *offset, int type, zval *rv)
diff --git a/ext/com_dotnet/com_saproxy.c b/ext/com_dotnet/com_saproxy.c
index e5b390bca6..abdca04334 100644
--- a/ext/com_dotnet/com_saproxy.c
+++ b/ext/com_dotnet/com_saproxy.c
@@ -69,7 +69,7 @@ static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, in
}
}
-static zval *saproxy_property_read(zval *object, zval *member, int type, void **cahce_slot, zval *rv)
+static zval *saproxy_property_read(zval *object, zval *member, int type, void **cache_slot, zval *rv)
{
ZVAL_NULL(rv);
diff --git a/ext/curl/multi.c b/ext/curl/multi.c
index cacda1aef4..1a891a4ebc 100644
--- a/ext/curl/multi.c
+++ b/ext/curl/multi.c
@@ -265,7 +265,7 @@ PHP_FUNCTION(curl_multi_exec)
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_RESOURCE(z_mh)
- Z_PARAM_ZVAL_DEREF(z_still_running)
+ Z_PARAM_ZVAL(z_still_running)
ZEND_PARSE_PARAMETERS_END();
if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
@@ -290,8 +290,7 @@ PHP_FUNCTION(curl_multi_exec)
still_running = zval_get_long(z_still_running);
error = curl_multi_perform(mh->multi, &still_running);
- zval_ptr_dtor(z_still_running);
- ZVAL_LONG(z_still_running, still_running);
+ ZEND_TRY_ASSIGN_LONG(z_still_running, still_running);
SAVE_CURLM_ERROR(mh, error);
RETURN_LONG((zend_long) error);
@@ -338,7 +337,7 @@ PHP_FUNCTION(curl_multi_info_read)
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_RESOURCE(z_mh)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(zmsgs_in_queue)
+ Z_PARAM_ZVAL(zmsgs_in_queue)
ZEND_PARSE_PARAMETERS_END();
if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
@@ -349,9 +348,9 @@ PHP_FUNCTION(curl_multi_info_read)
if (tmp_msg == NULL) {
RETURN_FALSE;
}
+
if (zmsgs_in_queue) {
- zval_ptr_dtor(zmsgs_in_queue);
- ZVAL_LONG(zmsgs_in_queue, queued_msgs);
+ ZEND_TRY_ASSIGN_LONG(zmsgs_in_queue, queued_msgs);
}
array_init(return_value);
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index f40ec15e07..eb56deb558 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -660,10 +660,10 @@ static HashTable *date_object_get_debug_info_timezone(zval *object, int *is_temp
static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv);
zval *date_interval_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv);
-void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot);
+zval *date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot);
static zval *date_interval_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot);
static zval *date_period_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv);
-static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot);
+static zval *date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot);
/* {{{ Module struct */
zend_module_entry date_module_entry = {
@@ -4211,7 +4211,7 @@ zval *date_interval_read_property(zval *object, zval *member, int type, void **c
/* }}} */
/* {{{ date_interval_write_property */
-void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+zval *date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
php_interval_obj *obj;
zval tmp_member;
@@ -4225,17 +4225,17 @@ void date_interval_write_property(zval *object, zval *member, zval *value, void
obj = Z_PHPINTERVAL_P(object);
if (!obj->initialized) {
- zend_std_write_property(object, member, value, cache_slot);
+ value = zend_std_write_property(object, member, value, cache_slot);
if (member == &tmp_member) {
zval_ptr_dtor_str(&tmp_member);
}
- return;
+ return value;
}
#define SET_VALUE_FROM_STRUCT(n,m) \
if (strcmp(Z_STRVAL_P(member), m) == 0) { \
obj->diff->n = zval_get_long(value); \
- break; \
+ break; \
}
do {
@@ -4251,12 +4251,14 @@ void date_interval_write_property(zval *object, zval *member, zval *value, void
}
SET_VALUE_FROM_STRUCT(invert, "invert");
/* didn't find any */
- zend_std_write_property(object, member, value, cache_slot);
+ value = zend_std_write_property(object, member, value, cache_slot);
} while(0);
if (member == &tmp_member) {
zval_ptr_dtor_str(&tmp_member);
}
+
+ return value;
}
/* }}} */
@@ -5295,9 +5297,10 @@ static zval *date_period_read_property(zval *object, zval *member, int type, voi
/* }}} */
/* {{{ date_period_write_property */
-static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+static zval *date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
zend_throw_error(NULL, "Writing to DatePeriod properties is unsupported");
+ return value;
}
/* }}} */
diff --git a/ext/date/tests/DateInterval_write_property_return.phpt b/ext/date/tests/DateInterval_write_property_return.phpt
new file mode 100644
index 0000000000..9c2c5c9137
--- /dev/null
+++ b/ext/date/tests/DateInterval_write_property_return.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Test that return value handling for DateInterval property writes do not corrupt RHS
+--FILE--
+<?php
+
+$interval = new DateInterval('P2Y4DT6H8M');
+$f = 0.5;
+var_dump($interval->f = $f);
+var_dump($f);
+
+?>
+--EXPECT--
+float(0.5)
+float(0.5)
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index 72ae3c3ffe..a25a185e01 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -356,7 +356,7 @@ zval *dom_read_property(zval *object, zval *member, int type, void **cache_slot,
/* }}} */
/* {{{ dom_write_property */
-void dom_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+zval *dom_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
dom_object *obj = Z_DOMOBJ_P(object);
zend_string *member_str = zval_get_string(member);
@@ -368,10 +368,12 @@ void dom_write_property(zval *object, zval *member, zval *value, void **cache_sl
if (hnd) {
hnd->write_func(obj, value);
} else {
- zend_std_write_property(object, member, value, cache_slot);
+ value = zend_std_write_property(object, member, value, cache_slot);
}
zend_string_release_ex(member_str, 0);
+
+ return value;
}
/* }}} */
diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c
index 6b778092f9..595d41e9d4 100644
--- a/ext/enchant/enchant.c
+++ b/ext/enchant/enchant.c
@@ -711,13 +711,15 @@ PHP_FUNCTION(enchant_dict_quick_check)
size_t wordlen;
enchant_dict *pdict;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|z/", &dict, &word, &wordlen, &sugg) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|z", &dict, &word, &wordlen, &sugg) == FAILURE) {
RETURN_FALSE;
}
if (sugg) {
- zval_ptr_dtor(sugg);
- array_init(sugg);
+ sugg = zend_try_array_init(sugg);
+ if (!sugg) {
+ return;
+ }
}
PHP_ENCHANT_GET_DICT;
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index 48e9372161..d37a61f83d 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -4606,9 +4606,9 @@ PHP_FUNCTION(exif_thumbnail)
ZEND_PARSE_PARAMETERS_START(1, 4)
Z_PARAM_ZVAL(stream)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(z_width)
- Z_PARAM_ZVAL_DEREF(z_height)
- Z_PARAM_ZVAL_DEREF(z_imagetype)
+ Z_PARAM_ZVAL(z_width)
+ Z_PARAM_ZVAL(z_height)
+ Z_PARAM_ZVAL(z_imagetype)
ZEND_PARSE_PARAMETERS_END();
memset(&ImageInfo, 0, sizeof(ImageInfo));
@@ -4653,14 +4653,11 @@ PHP_FUNCTION(exif_thumbnail)
if (!ImageInfo.Thumbnail.width || !ImageInfo.Thumbnail.height) {
exif_scan_thumbnail(&ImageInfo);
}
- zval_ptr_dtor(z_width);
- zval_ptr_dtor(z_height);
- ZVAL_LONG(z_width, ImageInfo.Thumbnail.width);
- ZVAL_LONG(z_height, ImageInfo.Thumbnail.height);
+ ZEND_TRY_ASSIGN_LONG(z_width, ImageInfo.Thumbnail.width);
+ ZEND_TRY_ASSIGN_LONG(z_height, ImageInfo.Thumbnail.height);
}
if (arg_c >= 4) {
- zval_ptr_dtor(z_imagetype);
- ZVAL_LONG(z_imagetype, ImageInfo.Thumbnail.filetype);
+ ZEND_TRY_ASSIGN_LONG(z_imagetype, ImageInfo.Thumbnail.filetype);
}
#ifdef EXIF_DEBUG
diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c
index 4b3a0fb306..5be151cb59 100644
--- a/ext/ftp/php_ftp.c
+++ b/ext/ftp/php_ftp.c
@@ -677,7 +677,7 @@ PHP_FUNCTION(ftp_alloc)
zend_long size, ret;
zend_string *response = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|z/", &z_ftp, &size, &zresponse) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|z", &z_ftp, &size, &zresponse) == FAILURE) {
RETURN_FALSE;
}
@@ -686,9 +686,9 @@ PHP_FUNCTION(ftp_alloc)
}
ret = ftp_alloc(ftp, size, zresponse ? &response : NULL);
+
if (response) {
- zval_ptr_dtor(zresponse);
- ZVAL_STR(zresponse, response);
+ ZEND_TRY_ASSIGN_STR(zresponse, response);
}
if (!ret) {
diff --git a/ext/intl/formatter/formatter_parse.c b/ext/intl/formatter/formatter_parse.c
index 347f929cbd..4ee14b3ce3 100644
--- a/ext/intl/formatter/formatter_parse.c
+++ b/ext/intl/formatter/formatter_parse.c
@@ -51,7 +51,7 @@ PHP_FUNCTION( numfmt_parse )
FORMATTER_METHOD_INIT_VARS;
/* Parse parameters. */
- if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|lz/!",
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os|lz!",
&object, NumberFormatter_ce_ptr, &str, &str_len, &type, &zposition ) == FAILURE )
{
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
@@ -60,6 +60,11 @@ PHP_FUNCTION( numfmt_parse )
RETURN_FALSE;
}
+ if(zposition) {
+ position = (int32_t) zval_get_long(zposition);
+ position_p = &position;
+ }
+
/* Fetch the object. */
FORMATTER_METHOD_FETCH_OBJECT;
@@ -67,12 +72,6 @@ PHP_FUNCTION( numfmt_parse )
intl_convert_utf8_to_utf16(&sstr, &sstr_len, str, str_len, &INTL_DATA_ERROR_CODE(nfo));
INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
- if(zposition) {
- ZVAL_DEREF(zposition);
- position = (int32_t)zval_get_long( zposition );
- position_p = &position;
- }
-
#if ICU_LOCALE_BUG && defined(LC_NUMERIC)
/* need to copy here since setlocale may change it later */
oldlocale = estrdup(setlocale(LC_NUMERIC, NULL));
@@ -106,8 +105,7 @@ PHP_FUNCTION( numfmt_parse )
efree(oldlocale);
#endif
if(zposition) {
- zval_ptr_dtor(zposition);
- ZVAL_LONG(zposition, position);
+ ZEND_TRY_ASSIGN_LONG(zposition, position);
}
if (sstr) {
@@ -138,7 +136,7 @@ PHP_FUNCTION( numfmt_parse_currency )
FORMATTER_METHOD_INIT_VARS;
/* Parse parameters. */
- if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Osz/|z/!",
+ if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Osz/|z!",
&object, NumberFormatter_ce_ptr, &str, &str_len, &zcurrency, &zposition ) == FAILURE )
{
intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
@@ -155,15 +153,13 @@ PHP_FUNCTION( numfmt_parse_currency )
INTL_METHOD_CHECK_STATUS( nfo, "String conversion to UTF-16 failed" );
if(zposition) {
- ZVAL_DEREF(zposition);
- position = (int32_t)zval_get_long( zposition );
+ position = (int32_t) zval_get_long(zposition);
position_p = &position;
}
number = unum_parseDoubleCurrency(FORMATTER_OBJECT(nfo), sstr, sstr_len, position_p, currency, &INTL_DATA_ERROR_CODE(nfo));
if(zposition) {
- zval_ptr_dtor(zposition);
- ZVAL_LONG(zposition, position);
+ ZEND_TRY_ASSIGN_LONG(zposition, position);
}
if (sstr) {
efree(sstr);
diff --git a/ext/intl/idn/idn.c b/ext/intl/idn/idn.c
index 305a944cce..d717d46ee2 100644
--- a/ext/intl/idn/idn.c
+++ b/ext/intl/idn/idn.c
@@ -259,7 +259,7 @@ static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode)
intl_error_reset(NULL);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|llz/",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|llz",
&domain, &option, &variant, &idna_info) == FAILURE) {
php_intl_bad_args("bad arguments");
RETURN_NULL(); /* don't set FALSE because that's not the way it was before... */
@@ -291,8 +291,10 @@ static void php_intl_idn_handoff(INTERNAL_FUNCTION_PARAMETERS, int mode)
"4 arguments were provided, but INTL_IDNA_VARIANT_2003 only "
"takes 3 - extra argument ignored");
} else {
- zval_ptr_dtor(idna_info);
- array_init(idna_info);
+ idna_info = zend_try_array_init(idna_info);
+ if (!idna_info) {
+ return;
+ }
}
}
diff --git a/ext/intl/transliterator/transliterator_class.c b/ext/intl/transliterator/transliterator_class.c
index e06ebd5c25..0f5d8cbf21 100644
--- a/ext/intl/transliterator/transliterator_class.c
+++ b/ext/intl/transliterator/transliterator_class.c
@@ -255,8 +255,7 @@ static zval *Transliterator_read_property( zval *object, zval *member, int type,
/* }}} */
/* {{{ write_property handler */
-static void Transliterator_write_property( zval *object, zval *member, zval *value,
- void **cache_slot )
+static zval *Transliterator_write_property( zval *object, zval *member, zval *value, void **cache_slot )
{
zend_class_entry *scope;
TRANSLITERATOR_PROPERTY_HANDLER_PROLOG;
@@ -274,10 +273,12 @@ static void Transliterator_write_property( zval *object, zval *member, zval *val
}
else
{
- zend_std_write_property( object, member, value, cache_slot );
+ value = zend_std_write_property( object, member, value, cache_slot );
}
TRANSLITERATOR_PROPERTY_HANDLER_EPILOG;
+
+ return value;
}
/* }}} */
diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c
index 1ddf1a77ca..0528ea08d7 100644
--- a/ext/ldap/ldap.c
+++ b/ext/ldap/ldap.c
@@ -576,7 +576,11 @@ static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* arr
zval tmp1;
LDAPControl **ctrlp;
- array_init(array);
+ array = zend_try_array_init(array);
+ if (!array) {
+ return;
+ }
+
if (ctrls == NULL) {
return;
}
@@ -2975,7 +2979,7 @@ PHP_FUNCTION(ldap_get_option)
ldap_linkdata *ld;
zend_long option;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz/", &link, &option, &retval) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz", &link, &option, &retval) != SUCCESS) {
return;
}
@@ -3017,8 +3021,7 @@ PHP_FUNCTION(ldap_get_option)
if (ldap_get_option(ld->link, option, &val)) {
RETURN_FALSE;
}
- zval_ptr_dtor(retval);
- ZVAL_LONG(retval, val);
+ ZEND_TRY_ASSIGN_LONG(retval, val);
} break;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
case LDAP_OPT_NETWORK_TIMEOUT:
@@ -3034,8 +3037,7 @@ PHP_FUNCTION(ldap_get_option)
if (!timeout) {
RETURN_FALSE;
}
- zval_ptr_dtor(retval);
- ZVAL_LONG(retval, timeout->tv_sec);
+ ZEND_TRY_ASSIGN_LONG(retval, timeout->tv_sec);
ldap_memfree(timeout);
} break;
#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
@@ -3046,8 +3048,7 @@ PHP_FUNCTION(ldap_get_option)
if (ldap_get_option(ld->link, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
RETURN_FALSE;
}
- zval_ptr_dtor(retval);
- ZVAL_LONG(retval, (timeout / 1000));
+ ZEND_TRY_ASSIGN_LONG(retval, (timeout / 1000));
} break;
#endif
#ifdef LDAP_OPT_TIMEOUT
@@ -3064,8 +3065,7 @@ PHP_FUNCTION(ldap_get_option)
if (!timeout) {
RETURN_FALSE;
}
- zval_ptr_dtor(retval);
- ZVAL_LONG(retval, timeout->tv_sec);
+ ZEND_TRY_ASSIGN_LONG(retval, timeout->tv_sec);
ldap_memfree(timeout);
} break;
#endif
@@ -3112,8 +3112,7 @@ PHP_FUNCTION(ldap_get_option)
}
RETURN_FALSE;
}
- zval_ptr_dtor(retval);
- ZVAL_STRING(retval, val);
+ ZEND_TRY_ASSIGN_STRING(retval, val);
ldap_memfree(val);
} break;
case LDAP_OPT_SERVER_CONTROLS:
@@ -3333,7 +3332,7 @@ PHP_FUNCTION(ldap_parse_result)
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
- if (zend_parse_parameters(myargcount, "rrz/|z/z/z/z/", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
+ if (zend_parse_parameters(myargcount, "rrz|zzzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) {
return;
}
@@ -3356,16 +3355,17 @@ PHP_FUNCTION(ldap_parse_result)
RETURN_FALSE;
}
- zval_ptr_dtor(errcode);
- ZVAL_LONG(errcode, lerrcode);
+ ZEND_TRY_ASSIGN_LONG(errcode, lerrcode);
/* Reverse -> fall through */
switch (myargcount) {
case 7:
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
case 6:
- zval_ptr_dtor(referrals);
- array_init(referrals);
+ referrals = zend_try_array_init(referrals);
+ if (!referrals) {
+ return;
+ }
if (lreferrals != NULL) {
refp = lreferrals;
while (*refp) {
@@ -3375,19 +3375,17 @@ PHP_FUNCTION(ldap_parse_result)
ldap_memvfree((void**)lreferrals);
}
case 5:
- zval_ptr_dtor(errmsg);
if (lerrmsg == NULL) {
- ZVAL_EMPTY_STRING(errmsg);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(errmsg);
} else {
- ZVAL_STRING(errmsg, lerrmsg);
+ ZEND_TRY_ASSIGN_STRING(errmsg, lerrmsg);
ldap_memfree(lerrmsg);
}
case 4:
- zval_ptr_dtor(matcheddn);
if (lmatcheddn == NULL) {
- ZVAL_EMPTY_STRING(matcheddn);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(matcheddn);
} else {
- ZVAL_STRING(matcheddn, lmatcheddn);
+ ZEND_TRY_ASSIGN_STRING(matcheddn, lmatcheddn);
ldap_memfree(lmatcheddn);
}
}
@@ -3398,7 +3396,7 @@ PHP_FUNCTION(ldap_parse_result)
/* {{{ Extended operation response parsing, Pierangelo Masarati */
#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
-/* {{{ proto bool ldap_parse_exop(resource link, resource result [, string retdata [, string retoid]])
+/* {{{ proto bool ldap_parse_exop(resource link, resource result [, string &retdata [, string &retoid]])
Extract information from extended operation result */
PHP_FUNCTION(ldap_parse_exop)
{
@@ -3409,7 +3407,7 @@ PHP_FUNCTION(ldap_parse_exop)
struct berval *lretdata;
int rc, myargcount = ZEND_NUM_ARGS();
- if (zend_parse_parameters(myargcount, "rr|z/z/", &link, &result, &retdata, &retoid) != SUCCESS) {
+ if (zend_parse_parameters(myargcount, "rr|zz", &link, &result, &retdata, &retoid) != SUCCESS) {
WRONG_PARAM_COUNT;
}
@@ -3433,20 +3431,18 @@ PHP_FUNCTION(ldap_parse_exop)
/* Reverse -> fall through */
switch (myargcount) {
case 4:
- zval_ptr_dtor(retoid);
if (lretoid == NULL) {
- ZVAL_EMPTY_STRING(retoid);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(retoid);
} else {
- ZVAL_STRING(retoid, lretoid);
+ ZEND_TRY_ASSIGN_STRING(retoid, lretoid);
ldap_memfree(lretoid);
}
case 3:
/* use arg #3 as the data returned by the server */
- zval_ptr_dtor(retdata);
if (lretdata == NULL) {
- ZVAL_EMPTY_STRING(retdata);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(retdata);
} else {
- ZVAL_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
+ ZEND_TRY_ASSIGN_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
ldap_memfree(lretdata->bv_val);
ldap_memfree(lretdata);
}
@@ -3524,7 +3520,7 @@ PHP_FUNCTION(ldap_next_reference)
/* }}} */
#ifdef HAVE_LDAP_PARSE_REFERENCE
-/* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array referrals)
+/* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array &referrals)
Extract information from reference entry */
PHP_FUNCTION(ldap_parse_reference)
{
@@ -3533,7 +3529,7 @@ PHP_FUNCTION(ldap_parse_reference)
ldap_resultentry *resultentry;
char **lreferrals, **refp;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz/", &link, &result_entry, &referrals) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz", &link, &result_entry, &referrals) != SUCCESS) {
return;
}
@@ -3549,8 +3545,11 @@ PHP_FUNCTION(ldap_parse_reference)
RETURN_FALSE;
}
- zval_ptr_dtor(referrals);
- array_init(referrals);
+ referrals = zend_try_array_init(referrals);
+ if (!referrals) {
+ return;
+ }
+
if (lreferrals != NULL) {
refp = lreferrals;
while (*refp) {
@@ -4015,7 +4014,7 @@ PHP_FUNCTION(ldap_control_paged_result_response)
ber_tag_t tag;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
- if (zend_parse_parameters(myargcount, "rr|z/z/", &link, &result, &cookie, &estimated) != SUCCESS) {
+ if (zend_parse_parameters(myargcount, "rr|zz", &link, &result, &cookie, &estimated) != SUCCESS) {
return;
}
@@ -4082,15 +4081,13 @@ PHP_FUNCTION(ldap_control_paged_result_response)
ldap_controls_free(lserverctrls);
if (myargcount == 4) {
- zval_ptr_dtor(estimated);
- ZVAL_LONG(estimated, lestimated);
+ ZEND_TRY_ASSIGN_LONG(estimated, lestimated);
}
- zval_ptr_dtor(cookie);
if (lcookie.bv_len == 0) {
- ZVAL_EMPTY_STRING(cookie);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(cookie);
} else {
- ZVAL_STRINGL(cookie, lcookie.bv_val, lcookie.bv_len);
+ ZEND_TRY_ASSIGN_STRINGL(cookie, lcookie.bv_val, lcookie.bv_len);
}
ldap_memfree(lcookie.bv_val);
@@ -4115,7 +4112,7 @@ PHP_FUNCTION(ldap_exop)
LDAPControl **lserverctrls = NULL;
int rc, msgid;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!a!z/z/", &link, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!a!zz", &link, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) {
return;
}
@@ -4153,22 +4150,20 @@ PHP_FUNCTION(ldap_exop)
}
if (retoid) {
- zval_ptr_dtor(retoid);
if (lretoid) {
- ZVAL_STRING(retoid, lretoid);
+ ZEND_TRY_ASSIGN_STRING(retoid, lretoid);
ldap_memfree(lretoid);
} else {
- ZVAL_EMPTY_STRING(retoid);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(retoid);
}
}
- zval_ptr_dtor(retdata);
if (lretdata) {
- ZVAL_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
+ ZEND_TRY_ASSIGN_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len);
ldap_memfree(lretdata->bv_val);
ldap_memfree(lretdata);
} else {
- ZVAL_EMPTY_STRING(retdata);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(retdata);
}
RETVAL_TRUE;
@@ -4219,7 +4214,7 @@ PHP_FUNCTION(ldap_exop_passwd)
int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
char* errmsg;
- if (zend_parse_parameters(myargcount, "r|zzzz/", &link, &user, &oldpw, &newpw, &serverctrls) == FAILURE) {
+ if (zend_parse_parameters(myargcount, "r|zzzz", &link, &user, &oldpw, &newpw, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index cdca12b00e..264c6020ca 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -2131,14 +2131,15 @@ PHP_FUNCTION(mb_parse_str)
const mbfl_encoding *detected;
track_vars_array = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z/", &encstr, &encstr_len, &track_vars_array) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z", &encstr, &encstr_len, &track_vars_array) == FAILURE) {
return;
}
if (track_vars_array != NULL) {
- /* Clear out the array */
- zval_ptr_dtor(track_vars_array);
- array_init(track_vars_array);
+ track_vars_array = zend_try_array_init(track_vars_array);
+ if (!track_vars_array) {
+ return;
+ }
}
encstr = estrndup(encstr, encstr_len);
diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c
index cc96e04f39..d443999f74 100644
--- a/ext/mbstring/php_mbregex.c
+++ b/ext/mbstring/php_mbregex.c
@@ -863,13 +863,15 @@ static void _php_mb_regex_ereg_exec(INTERNAL_FUNCTION_PARAMETERS, int icase)
OnigOptionType options;
char *str;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|z/", &arg_pattern, &string, &string_len, &array) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs|z", &arg_pattern, &string, &string_len, &array) == FAILURE) {
RETURN_FALSE;
}
if (array != NULL) {
- zval_ptr_dtor(array);
- array_init(array);
+ array = zend_try_array_init(array);
+ if (!array) {
+ return;
+ }
}
if (!php_mb_check_encoding(
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index f3d5e82309..b33ee41336 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -333,7 +333,7 @@ zval *mysqli_read_property(zval *object, zval *member, int type, void **cache_sl
/* }}} */
/* {{{ mysqli_write_property */
-void mysqli_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+zval *mysqli_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
zval tmp_member;
mysqli_object *obj;
@@ -353,12 +353,14 @@ void mysqli_write_property(zval *object, zval *member, zval *value, void **cache
if (hnd) {
hnd->write_func(obj, value);
} else {
- zend_std_write_property(object, member, value, cache_slot);
+ value = zend_std_write_property(object, member, value, cache_slot);
}
if (member == &tmp_member) {
zval_ptr_dtor_str(&tmp_member);
}
+
+ return value;
}
/* }}} */
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 40c7d2982d..e805da9fa7 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -967,17 +967,11 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
zval *result;
/* it must be a reference, isn't it? */
if (Z_ISREF(stmt->result.vars[i])) {
- result = Z_REFVAL(stmt->result.vars[i]);
+ result = stmt->result.vars[i];
} else {
- result = &stmt->result.vars[i];
+ continue; // but be safe ...
}
- /*
- QQ: Isn't it quite better to call zval_dtor(). What if the user has
- assigned a resource, or an array to the bound variable? We are going
- to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode.
- */
/* Even if the string is of length zero there is one byte alloced so efree() in all cases */
- zval_ptr_dtor(result);
if (!stmt->result.is_null[i]) {
switch (stmt->result.buf[i].type) {
case IS_LONG:
@@ -998,16 +992,16 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
} while (--j > 0);
tmp[10]= '\0';
/* unsigned int > INT_MAX is 10 digits - ALWAYS */
- ZVAL_STRINGL(result, tmp, 10);
+ ZEND_TRY_ASSIGN_STRINGL(result, tmp, 10);
efree(tmp);
break;
}
#endif
}
if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) {
- ZVAL_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
+ ZEND_TRY_ASSIGN_LONG(result, *(unsigned int *)stmt->result.buf[i].val);
} else {
- ZVAL_LONG(result, *(int *)stmt->result.buf[i].val);
+ ZEND_TRY_ASSIGN_LONG(result, *(int *)stmt->result.buf[i].val);
}
break;
case IS_DOUBLE:
@@ -1024,7 +1018,7 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
dval = *((double *)stmt->result.buf[i].val);
}
- ZVAL_DOUBLE(result, dval);
+ ZEND_TRY_ASSIGN_DOUBLE(result, dval);
break;
}
case IS_STRING:
@@ -1065,20 +1059,20 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
* use MYSQLI_LL_SPEC.
*/
snprintf(tmp, sizeof(tmp), (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? MYSQLI_LLU_SPEC : MYSQLI_LL_SPEC, llval);
- ZVAL_STRING(result, tmp);
+ ZEND_TRY_ASSIGN_STRING(result, tmp);
} else {
- ZVAL_LONG(result, llval);
+ ZEND_TRY_ASSIGN_LONG(result, llval);
}
} else {
#if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002
if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) {
/* result was truncated */
- ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
+ ZEND_TRY_ASSIGN_STRINGL(result, stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length);
} else {
#else
{
#endif
- ZVAL_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
+ ZEND_TRY_ASSIGN_STRINGL(result, stmt->result.buf[i].val, stmt->result.buf[i].output_len);
}
}
break;
@@ -1086,7 +1080,7 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
break;
}
} else {
- ZVAL_NULL(result);
+ ZEND_TRY_ASSIGN_NULL(result);
}
}
} else {
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index d8671b9da0..703c1f050a 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -761,15 +761,11 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, const unsign
}
for (i = 0; i < result->field_count; i++) {
- zval *result = &stmt->result_bind[i].zv;
-
- ZVAL_DEREF(result);
- /* Clean what we copied last time */
- zval_ptr_dtor(result);
/* copy the type */
+ zval *resultzv = &stmt->result_bind[i].zv;
if (stmt->result_bind[i].bound == TRUE) {
DBG_INF_FMT("i=%u type=%u", i, Z_TYPE(current_row[i]));
- ZVAL_COPY(result, &current_row[i]);
+ ZEND_TRY_ASSIGN_COPY_EX(resultzv, &current_row[i], 0);
}
}
}
@@ -849,17 +845,15 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsi
}
for (i = 0; i < field_count; i++) {
+ zval *resultzv = &stmt->result_bind[i].zv;
if (stmt->result_bind[i].bound == TRUE) {
zval *data = &result->unbuf->last_row_data[i];
- zval *result = &stmt->result_bind[i].zv;
if (Z_TYPE_P(data) == IS_STRING && (meta->fields[i].max_length < (zend_ulong) Z_STRLEN_P(data))){
meta->fields[i].max_length = Z_STRLEN_P(data);
}
- ZVAL_DEREF(result);
- zval_ptr_dtor(result);
- ZVAL_COPY_VALUE(result, data);
+ ZEND_TRY_ASSIGN_VALUE_EX(resultzv, data, 0);
/* copied data, thus also the ownership. Thus null data */
ZVAL_NULL(data);
}
@@ -1025,12 +1019,10 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned
/* If no result bind, do nothing. We consumed the data */
for (i = 0; i < field_count; i++) {
+ zval *resultzv = &stmt->result_bind[i].zv;
if (stmt->result_bind[i].bound == TRUE) {
zval *data = &result->unbuf->last_row_data[i];
- zval *result = &stmt->result_bind[i].zv;
- ZVAL_DEREF(result);
- zval_ptr_dtor(result);
DBG_INF_FMT("i=%u bound_var=%p type=%u refc=%u", i, &stmt->result_bind[i].zv,
Z_TYPE_P(data), Z_REFCOUNTED(stmt->result_bind[i].zv)?
Z_REFCOUNT(stmt->result_bind[i].zv) : 0);
@@ -1040,7 +1032,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned
meta->fields[i].max_length = Z_STRLEN_P(data);
}
- ZVAL_COPY_VALUE(result, data);
+ ZEND_TRY_ASSIGN_VALUE_EX(resultzv, data, 0);
/* copied data, thus also the ownership. Thus null data */
ZVAL_NULL(data);
}
@@ -1120,28 +1112,6 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
SET_EMPTY_ERROR(stmt->error_info);
SET_EMPTY_ERROR(conn->error_info);
- DBG_INF_FMT("result_bind=%p separated_once=%u", &stmt->result_bind, stmt->result_zvals_separated_once);
- /*
- The user might have not bound any variables for result.
- Do the binding once she does it.
- */
- if (stmt->result_bind && !stmt->result_zvals_separated_once) {
- unsigned int i;
- /*
- mysqlnd_stmt_store_result() has been called free the bind
- variables to prevent leaking of their previous content.
- */
- for (i = 0; i < stmt->result->field_count; i++) {
- if (stmt->result_bind[i].bound == TRUE) {
- zval *result = &stmt->result_bind[i].zv;
- ZVAL_DEREF(result);
- zval_ptr_dtor(result);
- ZVAL_NULL(result);
- }
- }
- stmt->result_zvals_separated_once = TRUE;
- }
-
ret = stmt->result->m.fetch_row(stmt->result, (void*)s, 0, fetched_anything);
DBG_RETURN(ret);
}
@@ -1537,7 +1507,6 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
}
mysqlnd_stmt_separate_result_bind(s);
- stmt->result_zvals_separated_once = FALSE;
stmt->result_bind = result_bind;
for (i = 0; i < stmt->field_count; i++) {
/* Prevent from freeing */
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 8a9018356e..a5c1359853 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -1309,7 +1309,6 @@ struct st_mysqlnd_stmt_data
unsigned char send_types_to_server;
MYSQLND_PARAM_BIND *param_bind;
MYSQLND_RESULT_BIND *result_bind;
- zend_bool result_zvals_separated_once;
MYSQLND_UPSERT_STATUS * upsert_status;
MYSQLND_UPSERT_STATUS upsert_status_impl;
diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c
index 2e05afa527..8eda816bd5 100644
--- a/ext/oci8/oci8_interface.c
+++ b/ext/oci8/oci8_interface.c
@@ -1473,7 +1473,7 @@ PHP_FUNCTION(oci_fetch_all)
ZEND_PARSE_PARAMETERS_START(2, 5)
Z_PARAM_RESOURCE(z_statement)
- Z_PARAM_ZVAL_DEREF_EX(array, 0, 1)
+ Z_PARAM_ZVAL(array)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(skip)
Z_PARAM_LONG(maxrows)
@@ -1482,20 +1482,21 @@ PHP_FUNCTION(oci_fetch_all)
PHP_OCI_ZVAL_TO_STATEMENT(z_statement, statement);
- zval_ptr_dtor(array);
-
while (skip--) {
if (php_oci_statement_fetch(statement, nrows)) {
- array_init(array);
+ zend_try_array_init(array);
RETURN_LONG(0);
}
}
if (flags & PHP_OCI_FETCHSTATEMENT_BY_ROW) {
/* Fetch by Row: array will contain one sub-array per query row */
- array_init(array);
- columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
+ array = zend_try_array_init(array);
+ if (!array) {
+ return;
+ }
+ columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
for (i = 0; i < statement->ncolumns; i++) {
columns[ i ] = php_oci_statement_get_column(statement, i + 1, NULL, 0);
}
@@ -1534,7 +1535,11 @@ PHP_FUNCTION(oci_fetch_all)
} else { /* default to BY_COLUMN */
/* Fetch by columns: array will contain one sub-array per query column */
- array_init_size(array, statement->ncolumns);
+ array = zend_try_array_init_size(array, statement->ncolumns);
+ if (!array) {
+ return;
+ }
+
columns = safe_emalloc(statement->ncolumns, sizeof(php_oci_out_column *), 0);
outarrs = safe_emalloc(statement->ncolumns, sizeof(zval*), 0);
diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
index b7b67562a4..9156347e83 100644
--- a/ext/odbc/php_odbc.c
+++ b/ext/odbc/php_odbc.c
@@ -1876,13 +1876,13 @@ PHP_FUNCTION(odbc_fetch_into)
#endif /* HAVE_SQL_EXTENDED_FETCH */
#ifdef HAVE_SQL_EXTENDED_FETCH
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) {
return;
}
rownum = pv_row;
#else
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/", &pv_res, &pv_res_arr) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &pv_res, &pv_res_arr) == FAILURE) {
return;
}
#endif /* HAVE_SQL_EXTENDED_FETCH */
@@ -1896,8 +1896,9 @@ PHP_FUNCTION(odbc_fetch_into)
RETURN_FALSE;
}
- if (Z_TYPE_P(pv_res_arr) != IS_ARRAY) {
- array_init(pv_res_arr);
+ pv_res_arr = zend_try_array_init(pv_res_arr);
+ if (!pv_res_arr) {
+ return;
}
#ifdef HAVE_SQL_EXTENDED_FETCH
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index 9e3a0ab9a1..397458365f 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -108,7 +108,7 @@ static uint32_t add_static_slot(HashTable *hash,
ret = Z_LVAL_P(pos);
} else {
ret = *cache_size;
- *cache_size += 2 * sizeof(void *);
+ *cache_size += (kind == LITERAL_STATIC_PROPERTY ? 3 : 2) * sizeof(void *);
ZVAL_LONG(&tmp, ret);
zend_hash_add(hash, key, &tmp);
}
@@ -183,6 +183,8 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
}
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS_CONST, 1);
break;
+ case ZEND_ASSIGN_STATIC_PROP:
+ case ZEND_ASSIGN_STATIC_PROP_REF:
case ZEND_FETCH_STATIC_PROP_R:
case ZEND_FETCH_STATIC_PROP_W:
case ZEND_FETCH_STATIC_PROP_RW:
@@ -191,6 +193,11 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
case ZEND_UNSET_STATIC_PROP:
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
+ case ZEND_PRE_INC_STATIC_PROP:
+ case ZEND_PRE_DEC_STATIC_PROP:
+ case ZEND_POST_INC_STATIC_PROP:
+ case ZEND_POST_DEC_STATIC_PROP:
+literals_handle_static_prop:
if (opline->op2_type == IS_CONST) {
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2);
}
@@ -210,6 +217,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
}
break;
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
case ZEND_FETCH_OBJ_R:
case ZEND_FETCH_OBJ_W:
case ZEND_FETCH_OBJ_RW:
@@ -238,6 +246,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case ZEND_ASSIGN_BW_OR:
case ZEND_ASSIGN_BW_AND:
case ZEND_ASSIGN_BW_XOR:
+ if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ goto literals_handle_static_prop;
+ }
if (opline->op2_type == IS_CONST) {
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1);
@@ -547,24 +558,48 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case ZEND_ASSIGN_BW_OR:
case ZEND_ASSIGN_BW_AND:
case ZEND_ASSIGN_BW_XOR:
- if (opline->extended_value != ZEND_ASSIGN_OBJ) {
- break;
+ if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ if (opline->op1_type == IS_CONST) {
+ // op1 static property
+ if (opline->op2_type == IS_CONST) {
+ (opline+1)->extended_value = add_static_slot(&hash, op_array,
+ opline->op2.constant,
+ opline->op1.constant,
+ LITERAL_STATIC_PROPERTY,
+ &cache_size);
+ } else {
+ (opline+1)->extended_value = cache_size;
+ cache_size += 3 * sizeof(void *);
+ }
+ } else if (opline->op2_type == IS_CONST) {
+ // op2 class
+ if (class_slot[opline->op2.constant] >= 0) {
+ (opline+1)->extended_value = class_slot[opline->op2.constant];
+ } else {
+ (opline+1)->extended_value = cache_size;
+ class_slot[opline->op2.constant] = cache_size;
+ cache_size += sizeof(void *);
+ }
+ }
}
- if (opline->op2_type == IS_CONST) {
- // op2 property
- if (opline->op1_type == IS_UNUSED &&
- property_slot[opline->op2.constant] >= 0) {
- (opline+1)->extended_value = property_slot[opline->op2.constant];
- } else {
- (opline+1)->extended_value = cache_size;
- cache_size += 2 * sizeof(void *);
- if (opline->op1_type == IS_UNUSED) {
- property_slot[opline->op2.constant] = (opline+1)->extended_value;
+ if (opline->extended_value == ZEND_ASSIGN_OBJ) {
+ if (opline->op2_type == IS_CONST) {
+ // op2 property
+ if (opline->op1_type == IS_UNUSED &&
+ property_slot[opline->op2.constant] >= 0) {
+ (opline+1)->extended_value = property_slot[opline->op2.constant];
+ } else {
+ (opline+1)->extended_value = cache_size;
+ cache_size += 3 * sizeof(void *);
+ if (opline->op1_type == IS_UNUSED) {
+ property_slot[opline->op2.constant] = (opline+1)->extended_value;
+ }
}
}
}
break;
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
case ZEND_FETCH_OBJ_R:
case ZEND_FETCH_OBJ_W:
case ZEND_FETCH_OBJ_RW:
@@ -580,12 +615,12 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
// op2 property
if (opline->op1_type == IS_UNUSED &&
property_slot[opline->op2.constant] >= 0) {
- opline->extended_value = property_slot[opline->op2.constant];
+ opline->extended_value = property_slot[opline->op2.constant] | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
} else {
- opline->extended_value = cache_size;
- cache_size += 2 * sizeof(void *);
+ opline->extended_value = cache_size | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
+ cache_size += 3 * sizeof(void *);
if (opline->op1_type == IS_UNUSED) {
- property_slot[opline->op2.constant] = opline->extended_value;
+ property_slot[opline->op2.constant] = opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS;
}
}
}
@@ -598,7 +633,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
opline->extended_value = property_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISEMPTY);
} else {
opline->extended_value = cache_size | (opline->extended_value & ZEND_ISEMPTY);
- cache_size += 2 * sizeof(void *);
+ cache_size += 3 * sizeof(void *);
if (opline->op1_type == IS_UNUSED) {
property_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISEMPTY;
}
@@ -689,6 +724,8 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
cache_size += 2 * sizeof(void *);
}
break;
+ case ZEND_ASSIGN_STATIC_PROP:
+ case ZEND_ASSIGN_STATIC_PROP_REF:
case ZEND_FETCH_STATIC_PROP_R:
case ZEND_FETCH_STATIC_PROP_W:
case ZEND_FETCH_STATIC_PROP_RW:
@@ -696,30 +733,11 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case ZEND_FETCH_STATIC_PROP_UNSET:
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
case ZEND_UNSET_STATIC_PROP:
- if (opline->op1_type == IS_CONST) {
- // op1 static property
- if (opline->op2_type == IS_CONST) {
- opline->extended_value = add_static_slot(&hash, op_array,
- opline->op2.constant,
- opline->op1.constant,
- LITERAL_STATIC_PROPERTY,
- &cache_size);
- } else {
- opline->extended_value = cache_size;
- cache_size += 2 * sizeof(void *);
- }
- } else if (opline->op2_type == IS_CONST) {
- // op2 class
- if (class_slot[opline->op2.constant] >= 0) {
- opline->extended_value = class_slot[opline->op2.constant];
- } else {
- opline->extended_value = cache_size;
- cache_size += sizeof(void *);
- class_slot[opline->op2.constant] = opline->extended_value;
- }
- }
- break;
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
+ case ZEND_PRE_INC_STATIC_PROP:
+ case ZEND_PRE_DEC_STATIC_PROP:
+ case ZEND_POST_INC_STATIC_PROP:
+ case ZEND_POST_DEC_STATIC_PROP:
if (opline->op1_type == IS_CONST) {
// op1 static property
if (opline->op2_type == IS_CONST) {
@@ -727,19 +745,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
opline->op2.constant,
opline->op1.constant,
LITERAL_STATIC_PROPERTY,
- &cache_size) | (opline->extended_value & ZEND_ISEMPTY);
+ &cache_size) | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
} else {
- opline->extended_value = cache_size | (opline->extended_value & ZEND_ISEMPTY);
- cache_size += 2 * sizeof(void *);
+ opline->extended_value = cache_size | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
+ cache_size += 3 * sizeof(void *);
}
} else if (opline->op2_type == IS_CONST) {
// op2 class
if (class_slot[opline->op2.constant] >= 0) {
- opline->extended_value = class_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISEMPTY);
+ opline->extended_value = class_slot[opline->op2.constant] | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
} else {
- opline->extended_value = cache_size | (opline->extended_value & ZEND_ISEMPTY);
+ opline->extended_value = cache_size | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
+ class_slot[opline->op2.constant] = cache_size;
cache_size += sizeof(void *);
- class_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISEMPTY;
}
}
break;
diff --git a/ext/opcache/Optimizer/dce.c b/ext/opcache/Optimizer/dce.c
index 89898393a7..95755d559f 100644
--- a/ext/opcache/Optimizer/dce.c
+++ b/ext/opcache/Optimizer/dce.c
@@ -330,6 +330,9 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z
case ZEND_ASSIGN_REF:
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
+ case ZEND_ASSIGN_STATIC_PROP:
+ case ZEND_ASSIGN_STATIC_PROP_REF:
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
case ZEND_ASSIGN_MUL:
diff --git a/ext/opcache/Optimizer/escape_analysis.c b/ext/opcache/Optimizer/escape_analysis.c
index f88de6202a..a92d773783 100644
--- a/ext/opcache/Optimizer/escape_analysis.c
+++ b/ext/opcache/Optimizer/escape_analysis.c
@@ -217,6 +217,7 @@ static int is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, in
break;
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
if (OP1_INFO() & (MAY_BE_UNDEF | MAY_BE_NULL | MAY_BE_FALSE)) {
/* implicit object/array allocation */
return 1;
@@ -259,6 +260,7 @@ static int is_local_def(zend_op_array *op_array, zend_ssa *ssa, int def, int var
return 1;
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
return 1;
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
@@ -328,6 +330,7 @@ static int is_escape_use(zend_op_array *op_array, zend_ssa *ssa, int use, int va
/* break missing intentionally */
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
break;
case ZEND_PRE_INC_OBJ:
case ZEND_PRE_DEC_OBJ:
@@ -508,7 +511,8 @@ int zend_ssa_escape_analysis(const zend_script *script, zend_op_array *op_array,
if (opline->opcode == ZEND_OP_DATA &&
((opline-1)->opcode == ZEND_ASSIGN_DIM ||
- (opline-1)->opcode == ZEND_ASSIGN_OBJ) &&
+ (opline-1)->opcode == ZEND_ASSIGN_OBJ ||
+ (opline-1)->opcode == ZEND_ASSIGN_OBJ_REF) &&
op->op1_use == i &&
(op-1)->op1_use >= 0) {
enclosing_root = ees[(op-1)->op1_use];
diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c
index 08e1584923..69a3e81c6b 100644
--- a/ext/opcache/Optimizer/sccp.c
+++ b/ext/opcache/Optimizer/sccp.c
@@ -203,6 +203,7 @@ static zend_bool can_replace_op1(
case ZEND_ASSIGN_REF:
case ZEND_ASSIGN_DIM:
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
case ZEND_ASSIGN_MUL:
@@ -251,6 +252,9 @@ static zend_bool can_replace_op1(
case ZEND_VERIFY_RETURN_TYPE:
// TODO: This would require a non-local change ???
return 0;
+ case ZEND_OP_DATA:
+ return (opline - 1)->opcode != ZEND_ASSIGN_OBJ_REF &&
+ (opline - 1)->opcode != ZEND_ASSIGN_STATIC_PROP_REF;
default:
if (ssa_op->op1_def != -1) {
ZEND_ASSERT(0);
@@ -1400,7 +1404,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
if (op2) {
SKIP_IF_TOP(op2);
}
- if (!opline->extended_value) {
+ if (opline->extended_value == 0) {
if (zend_optimizer_eval_binary_op(&zv, zend_compound_assign_to_binary_op(opline->opcode), op1, op2) == SUCCESS) {
SET_RESULT(op1, &zv);
SET_RESULT(result, &zv);
@@ -1494,6 +1498,11 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
zval_ptr_dtor_nogc(&zv);
}
}
+ } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ SET_RESULT_BOT(result);
+ break;
+ } else {
+ ZEND_ASSERT(0 && "Invalid compound assignment kind");
}
SET_RESULT_BOT(result);
SET_RESULT_BOT(op1);
diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c
index 4430f193a8..66dd15da00 100644
--- a/ext/opcache/Optimizer/zend_dfg.c
+++ b/ext/opcache/Optimizer/zend_dfg.c
@@ -52,8 +52,14 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
if (next < end && next->opcode == ZEND_OP_DATA) {
if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
var_num = EX_VAR_TO_NUM(next->op1.var);
- if (!DFG_ISSET(def, set_size, j, var_num)) {
+ if (opline->opcode == ZEND_ASSIGN_OBJ_REF
+ || opline->opcode == ZEND_ASSIGN_STATIC_PROP_REF) {
DFG_SET(use, set_size, j, var_num);
+ DFG_SET(def, set_size, j, var_num);
+ } else {
+ if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
+ }
}
}
if (next->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
@@ -92,6 +98,7 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
case ZEND_UNSET_CV:
case ZEND_ASSIGN:
case ZEND_ASSIGN_REF:
+ case ZEND_ASSIGN_OBJ_REF:
case ZEND_BIND_GLOBAL:
case ZEND_BIND_STATIC:
case ZEND_SEND_VAR_EX:
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c
index 90107785b7..d5f6c4564b 100644
--- a/ext/opcache/Optimizer/zend_dump.c
+++ b/ext/opcache/Optimizer/zend_dump.c
@@ -451,6 +451,8 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
fprintf(stderr, " (dim)");
} else if (opline->extended_value == ZEND_ASSIGN_OBJ) {
fprintf(stderr, " (obj)");
+ } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ fprintf(stderr, " (static prop)");
}
} else if (ZEND_VM_EXT_TYPE == (flags & ZEND_VM_EXT_MASK)) {
switch (opline->extended_value) {
@@ -554,7 +556,7 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
} else if (ZEND_VM_EXT_SRC == (flags & ZEND_VM_EXT_MASK)) {
if (opline->extended_value == ZEND_RETURNS_VALUE) {
fprintf(stderr, " (value)");
- } else if (opline->extended_value == ZEND_RETURNS_FUNCTION) {
+ } else if (opline->extended_value & ZEND_RETURNS_FUNCTION) {
fprintf(stderr, " (function)");
}
} else {
@@ -585,6 +587,16 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *
fprintf(stderr, " (ref)");
}
}
+ if ((ZEND_VM_EXT_DIM_OBJ_WRITE|ZEND_VM_EXT_FETCH_REF) & flags) {
+ uint32_t obj_flags = opline->extended_value & ZEND_FETCH_OBJ_FLAGS;
+ if (obj_flags == ZEND_FETCH_REF) {
+ fprintf(stderr, " (ref)");
+ } else if (obj_flags == ZEND_FETCH_DIM_WRITE) {
+ fprintf(stderr, " (dim write)");
+ } else if (obj_flags == ZEND_FETCH_OBJ_WRITE) {
+ fprintf(stderr, " (obj write)");
+ }
+ }
}
if (opline->op1_type == IS_CONST) {
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index 9f1dfdba20..980f3c5fea 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -2240,6 +2240,24 @@ static inline zend_class_entry *get_class_entry(const zend_script *script, zend_
return NULL;
}
+static uint32_t zend_convert_type_code_to_may_be(zend_uchar type_code) {
+ switch (type_code) {
+ case IS_VOID:
+ return MAY_BE_NULL;
+ case IS_CALLABLE:
+ return MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
+ case IS_ITERABLE:
+ return MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
+ case IS_ARRAY:
+ return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
+ case _IS_BOOL:
+ return MAY_BE_TRUE|MAY_BE_FALSE;
+ default:
+ ZEND_ASSERT(type_code < IS_REFERENCE);
+ return 1 << type_code;
+ }
+}
+
static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *arg_info, zend_class_entry **pce)
{
uint32_t tmp = 0;
@@ -2252,22 +2270,7 @@ static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *ar
*pce = get_class_entry(script, lcname);
zend_string_release_ex(lcname, 0);
} else if (ZEND_TYPE_IS_CODE(arg_info->type)) {
- zend_uchar type_hint = ZEND_TYPE_CODE(arg_info->type);
-
- if (type_hint == IS_VOID) {
- tmp |= MAY_BE_NULL;
- } else if (type_hint == IS_CALLABLE) {
- tmp |= MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
- } else if (type_hint == IS_ITERABLE) {
- tmp |= MAY_BE_OBJECT|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
- } else if (type_hint == IS_ARRAY) {
- tmp |= MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
- } else if (type_hint == _IS_BOOL) {
- tmp |= MAY_BE_TRUE|MAY_BE_FALSE;
- } else {
- ZEND_ASSERT(type_hint < IS_REFERENCE);
- tmp |= 1 << type_hint;
- }
+ tmp |= zend_convert_type_code_to_may_be(ZEND_TYPE_CODE(arg_info->type));
} else {
tmp |= MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
}
@@ -2277,6 +2280,123 @@ static uint32_t zend_fetch_arg_info(const zend_script *script, zend_arg_info *ar
return tmp;
}
+static zend_property_info *lookup_prop_info(zend_class_entry *ce, zend_string *name, zend_class_entry *scope) {
+ zend_property_info *prop_info;
+
+ /* If the class is linked, reuse the precise runtime logic. */
+ if (ce->ce_flags & ZEND_ACC_LINKED) {
+ zend_class_entry *prev_scope = EG(fake_scope);
+ EG(fake_scope) = scope;
+ prop_info = zend_get_property_info(ce, name, 1);
+ EG(fake_scope) = prev_scope;
+ if (prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO) {
+ return prop_info;
+ }
+ return NULL;
+ }
+
+ /* Otherwise, handle only some safe cases */
+ prop_info = zend_hash_find_ptr(&ce->properties_info, name);
+ if (prop_info &&
+ ((prop_info->ce == scope) ||
+ (!scope && (prop_info->flags & ZEND_ACC_PUBLIC)))
+ ) {
+ return prop_info;
+ }
+ return NULL;
+}
+
+static zend_property_info *zend_fetch_prop_info(const zend_op_array *op_array, zend_ssa *ssa, zend_op *opline, int i)
+{
+ zend_property_info *prop_info = NULL;
+ if (opline->op2_type == IS_CONST) {
+ zend_class_entry *ce = NULL;
+
+ if (opline->op1_type == IS_UNUSED) {
+ ce = op_array->scope;
+ } else if (ssa->ops[i].op1_use >= 0) {
+ ce = ssa->var_info[ssa->ops[i].op1_use].ce;
+ }
+ if (ce) {
+ prop_info = lookup_prop_info(ce,
+ Z_STR_P(CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants)),
+ op_array->scope);
+ if (prop_info && (prop_info->flags & ZEND_ACC_STATIC)) {
+ prop_info = NULL;
+ }
+ }
+ }
+ return prop_info;
+}
+
+static zend_property_info *zend_fetch_static_prop_info(const zend_script *script, const zend_op_array *op_array, zend_ssa *ssa, zend_op *opline)
+{
+ zend_property_info *prop_info = NULL;
+ if (opline->op1_type == IS_CONST) {
+ zend_class_entry *ce = NULL;
+ if (opline->op2_type == IS_UNUSED) {
+ int fetch_type = opline->op2.num & ZEND_FETCH_CLASS_MASK;
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ case ZEND_FETCH_CLASS_STATIC:
+ /* We enforce that static property types cannot change during inheritance, so
+ * handling static the same way as self here is legal. */
+ ce = op_array->scope;
+ break;
+ case ZEND_FETCH_CLASS_PARENT:
+ if (op_array->scope) {
+ ce = op_array->scope->parent;
+ }
+ break;
+ }
+ } else if (opline->op2_type == IS_CONST) {
+ zval *zv = CRT_CONSTANT_EX(op_array, opline, opline->op2, ssa->rt_constants);
+ ce = get_class_entry(script, Z_STR_P(zv + 1));
+ }
+
+ if (ce) {
+ zval *zv = CRT_CONSTANT_EX(op_array, opline, opline->op1, ssa->rt_constants);
+ prop_info = lookup_prop_info(ce, Z_STR_P(zv), op_array->scope);
+ if (prop_info && !(prop_info->flags & ZEND_ACC_STATIC)) {
+ prop_info = NULL;
+ }
+ }
+ }
+ return prop_info;
+}
+
+static uint32_t zend_fetch_prop_type(const zend_script *script, zend_property_info *prop_info, zend_class_entry **pce)
+{
+ if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
+ uint32_t type = ZEND_TYPE_IS_CLASS(prop_info->type)
+ ? MAY_BE_OBJECT
+ : zend_convert_type_code_to_may_be(ZEND_TYPE_CODE(prop_info->type));
+
+ if (ZEND_TYPE_ALLOW_NULL(prop_info->type)) {
+ type |= MAY_BE_NULL;
+ }
+ if (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
+ type |= MAY_BE_RC1 | MAY_BE_RCN;
+ }
+ if (pce) {
+ if (ZEND_TYPE_IS_CE(prop_info->type)) {
+ *pce = ZEND_TYPE_CE(prop_info->type);
+ } else if (ZEND_TYPE_IS_NAME(prop_info->type)) {
+ zend_string *lcname = zend_string_tolower(ZEND_TYPE_NAME(prop_info->type));
+ *pce = get_class_entry(script, lcname);
+ zend_string_release(lcname);
+ } else {
+ *pce = NULL;
+ }
+ }
+ return type;
+ }
+ if (pce) {
+ *pce = NULL;
+ }
+ return MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_RC1 | MAY_BE_RCN;
+}
+
static int zend_update_type_info(const zend_op_array *op_array,
zend_ssa *ssa,
const zend_script *script,
@@ -2474,13 +2594,14 @@ static int zend_update_type_info(const zend_op_array *op_array,
case ZEND_ASSIGN_BW_OR:
case ZEND_ASSIGN_BW_AND:
case ZEND_ASSIGN_BW_XOR:
- case ZEND_ASSIGN_CONCAT:
+ case ZEND_ASSIGN_CONCAT: {
+ zend_property_info *prop_info = NULL;
orig = 0;
tmp = 0;
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
- tmp |= MAY_BE_REF;
+ prop_info = zend_fetch_prop_info(op_array, ssa, opline, i);
orig = t1;
- t1 = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
+ t1 = zend_fetch_prop_type(script, prop_info, &ce);
t2 = OP1_DATA_INFO();
} else if (opline->extended_value == ZEND_ASSIGN_DIM) {
if (t1 & MAY_BE_ARRAY_OF_REF) {
@@ -2489,6 +2610,10 @@ static int zend_update_type_info(const zend_op_array *op_array,
orig = t1;
t1 = zend_array_element_type(t1, 1, 0);
t2 = OP1_DATA_INFO();
+ } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline);
+ t1 = zend_fetch_prop_type(script, prop_info, &ce);
+ t2 = OP1_DATA_INFO();
} else {
if (t1 & MAY_BE_REF) {
tmp |= MAY_BE_REF;
@@ -2524,10 +2649,13 @@ static int zend_update_type_info(const zend_op_array *op_array,
UPDATE_SSA_TYPE(orig, ssa_ops[i].op1_def);
COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
}
+ } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ /* Nothing to do */
} else {
UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
}
if (ssa_ops[i].result_def >= 0) {
+ ce = NULL;
if (opline->extended_value == ZEND_ASSIGN_DIM) {
if (opline->op2_type == IS_UNUSED) {
/* When appending to an array and the LONG_MAX key is already used
@@ -2549,10 +2677,25 @@ static int zend_update_type_info(const zend_op_array *op_array,
* anything else results in a null return value. */
tmp |= MAY_BE_NULL;
}
+
+ /* The return value must also satisfy the property type */
+ if (prop_info) {
+ tmp &= zend_fetch_prop_type(script, prop_info, NULL);
+ }
+ } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ /* The return value must also satisfy the property type */
+ if (prop_info) {
+ tmp &= zend_fetch_prop_type(script, prop_info, NULL);
+ }
}
+ tmp &= ~MAY_BE_REF;
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
+ if (ce) {
+ UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
+ }
}
break;
+ }
case ZEND_PRE_INC:
case ZEND_PRE_DEC:
tmp = 0;
@@ -2727,9 +2870,13 @@ static int zend_update_type_info(const zend_op_array *op_array,
COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
}
if (ssa_ops[i].result_def >= 0) {
- // TODO: ???
- tmp = MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
+ // TODO: If there is no __set we might do better
+ tmp = zend_fetch_prop_type(script,
+ zend_fetch_prop_info(op_array, ssa, opline, i), &ce);
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
+ if (ce) {
+ UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
+ }
}
if ((opline+1)->op1_type == IS_CV) {
opline++;
@@ -2827,6 +2974,42 @@ static int zend_update_type_info(const zend_op_array *op_array,
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
}
break;
+ case ZEND_ASSIGN_OBJ_REF:
+ if (opline->op1_type == IS_CV) {
+ tmp = t1;
+ if (t1 & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE)) {
+ tmp &= ~(MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE);
+ tmp |= MAY_BE_OBJECT | MAY_BE_RC1 | MAY_BE_RCN;
+ }
+ if (tmp & MAY_BE_OBJECT) {
+ tmp |= MAY_BE_RC1 | MAY_BE_RCN;
+ }
+ UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
+ COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
+ }
+
+ t2 = OP1_DATA_INFO();
+ if ((opline+1)->op1_type == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION)) {
+ tmp = (MAY_BE_REF | MAY_BE_RCN | MAY_BE_RC1 | t2) & ~MAY_BE_UNDEF;
+ } else {
+ tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_ERROR|MAY_BE_RC1|MAY_BE_RCN);
+ }
+ if (t2 & MAY_BE_UNDEF) {
+ tmp |= MAY_BE_NULL;
+ }
+ if (ssa_ops[i].result_def >= 0) {
+ UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
+ }
+ if ((opline+1)->op1_type == IS_CV) {
+ opline++;
+ i++;
+ tmp = (MAY_BE_REF | t2) & ~(MAY_BE_UNDEF|MAY_BE_RC1|MAY_BE_RCN);
+ if (t2 & MAY_BE_UNDEF) {
+ tmp |= MAY_BE_NULL;
+ }
+ UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
+ }
+ break;
case ZEND_BIND_GLOBAL:
tmp = MAY_BE_REF | MAY_BE_ANY
| MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
@@ -3245,6 +3428,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
case ZEND_FETCH_OBJ_RW:
case ZEND_FETCH_OBJ_FUNC_ARG:
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
case ZEND_PRE_INC_OBJ:
case ZEND_PRE_DEC_OBJ:
case ZEND_POST_INC_OBJ:
@@ -3342,14 +3526,31 @@ static int zend_update_type_info(const zend_op_array *op_array,
COPY_SSA_OBJ_TYPE(ssa_ops[i].op1_use, ssa_ops[i].op1_def);
}
if (ssa_ops[i].result_def >= 0) {
- tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
- if (opline->result_type == IS_TMP_VAR) {
- /* can't be REF because of ZVAL_COPY_DEREF() usage */
- tmp |= MAY_BE_RC1 | MAY_BE_RCN;
- } else {
- tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ERROR;
+ tmp = zend_fetch_prop_type(script,
+ zend_fetch_prop_info(op_array, ssa, opline, i), &ce);
+ if (opline->result_type != IS_TMP_VAR) {
+ tmp |= MAY_BE_REF | MAY_BE_ERROR;
}
UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
+ if (ce) {
+ UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
+ }
+ }
+ break;
+ case ZEND_FETCH_STATIC_PROP_R:
+ case ZEND_FETCH_STATIC_PROP_IS:
+ case ZEND_FETCH_STATIC_PROP_RW:
+ case ZEND_FETCH_STATIC_PROP_W:
+ case ZEND_FETCH_STATIC_PROP_UNSET:
+ case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
+ tmp = zend_fetch_prop_type(script,
+ zend_fetch_static_prop_info(script, op_array, ssa, opline), &ce);
+ if (opline->result_type != IS_TMP_VAR) {
+ tmp |= MAY_BE_REF | MAY_BE_ERROR;
+ }
+ UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def);
+ if (ce) {
+ UPDATE_SSA_OBJ_TYPE(ce, 1, ssa_ops[i].result_def);
}
break;
case ZEND_DO_FCALL:
@@ -4182,7 +4383,7 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa
return 1;
}
}
- } else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+ } else if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
if (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY)) {
switch (opline->opcode) {
case ZEND_CASE:
@@ -4206,9 +4407,9 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa
return 1;
}
}
- }
+ }
- if (opline->op2_type == IS_CV) {
+ if (opline->op2_type == IS_CV) {
if (t2 & MAY_BE_UNDEF) {
switch (opline->opcode) {
case ZEND_ASSIGN_REF:
@@ -4228,7 +4429,7 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa
return 1;
}
}
- }
+ }
switch (opline->opcode) {
case ZEND_NOP:
@@ -4390,6 +4591,9 @@ int zend_may_throw(const zend_op *opline, zend_op_array *op_array, zend_ssa *ssa
return (t1 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT)) ||
(t2 & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT));
case ZEND_ASSIGN:
+ if (t1 & MAY_BE_REF) {
+ return 1;
+ }
case ZEND_UNSET_VAR:
return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_ARRAY));
case ZEND_ASSIGN_DIM:
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index d13b8a000e..42cd5eef8f 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -256,6 +256,14 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
zval *val)
{
switch (opline->opcode) {
+ case ZEND_OP_DATA:
+ switch ((opline-1)->opcode) {
+ case ZEND_ASSIGN_OBJ_REF:
+ case ZEND_ASSIGN_STATIC_PROP_REF:
+ return 0;
+ }
+ opline->op1.constant = zend_optimizer_add_literal(op_array, val);
+ break;
case ZEND_FREE:
case ZEND_CHECK_VAR:
MAKE_NOP(opline);
@@ -312,6 +320,23 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
}
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
break;
+ case ZEND_ASSIGN_ADD:
+ case ZEND_ASSIGN_SUB:
+ case ZEND_ASSIGN_MUL:
+ case ZEND_ASSIGN_DIV:
+ case ZEND_ASSIGN_MOD:
+ case ZEND_ASSIGN_SL:
+ case ZEND_ASSIGN_SR:
+ case ZEND_ASSIGN_CONCAT:
+ case ZEND_ASSIGN_BW_OR:
+ case ZEND_ASSIGN_BW_AND:
+ case ZEND_ASSIGN_BW_XOR:
+ case ZEND_ASSIGN_POW:
+ if (opline->extended_value != ZEND_ASSIGN_STATIC_PROP) {
+ break;
+ }
+ case ZEND_ASSIGN_STATIC_PROP:
+ case ZEND_ASSIGN_STATIC_PROP_REF:
case ZEND_FETCH_STATIC_PROP_R:
case ZEND_FETCH_STATIC_PROP_W:
case ZEND_FETCH_STATIC_PROP_RW:
@@ -319,21 +344,17 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
case ZEND_FETCH_STATIC_PROP_UNSET:
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
case ZEND_UNSET_STATIC_PROP:
- TO_STRING_NOWARN(val);
- opline->op1.constant = zend_optimizer_add_literal(op_array, val);
- if (opline->op2_type == IS_CONST && opline->extended_value + sizeof(void*) == op_array->cache_size) {
- op_array->cache_size += sizeof(void *);
- } else {
- opline->extended_value = alloc_cache_slots(op_array, 2);
- }
- break;
case ZEND_ISSET_ISEMPTY_STATIC_PROP:
+ case ZEND_PRE_INC_STATIC_PROP:
+ case ZEND_PRE_DEC_STATIC_PROP:
+ case ZEND_POST_INC_STATIC_PROP:
+ case ZEND_POST_DEC_STATIC_PROP:
TO_STRING_NOWARN(val);
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
- if (opline->op2_type == IS_CONST && (opline->extended_value & ~ZEND_ISEMPTY) + sizeof(void*) == op_array->cache_size) {
+ if (opline->op2_type == IS_CONST && (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) + sizeof(void*) == op_array->cache_size) {
op_array->cache_size += sizeof(void *);
} else {
- opline->extended_value = alloc_cache_slots(op_array, 2) | (opline->extended_value & ZEND_ISEMPTY);
+ opline->extended_value = alloc_cache_slots(op_array, 3) | (opline->extended_value & ZEND_FETCH_OBJ_FLAGS);
}
break;
case ZEND_SEND_VAR:
@@ -405,6 +426,8 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
opline->result.num = alloc_cache_slots(op_array, 1);
break;
+ case ZEND_ASSIGN_STATIC_PROP:
+ case ZEND_ASSIGN_STATIC_PROP_REF:
case ZEND_FETCH_STATIC_PROP_R:
case ZEND_FETCH_STATIC_PROP_W:
case ZEND_FETCH_STATIC_PROP_RW:
@@ -412,21 +435,17 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
case ZEND_FETCH_STATIC_PROP_UNSET:
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
case ZEND_UNSET_STATIC_PROP:
+ case ZEND_PRE_INC_STATIC_PROP:
+ case ZEND_PRE_DEC_STATIC_PROP:
+ case ZEND_POST_INC_STATIC_PROP:
+ case ZEND_POST_DEC_STATIC_PROP:
+handle_static_prop:
REQUIRES_STRING(val);
drop_leading_backslash(val);
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
if (opline->op1_type != IS_CONST) {
- opline->extended_value = alloc_cache_slots(op_array, 1);
- }
- break;
- case ZEND_ISSET_ISEMPTY_STATIC_PROP:
- REQUIRES_STRING(val);
- drop_leading_backslash(val);
- opline->op2.constant = zend_optimizer_add_literal(op_array, val);
- zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
- if (opline->op1_type != IS_CONST) {
- opline->extended_value = alloc_cache_slots(op_array, 1) | (opline->extended_value & ZEND_ISEMPTY);
+ opline->extended_value = alloc_cache_slots(op_array, 1) | (opline->extended_value & (ZEND_RETURNS_FUNCTION|ZEND_ISEMPTY|ZEND_FETCH_OBJ_FLAGS));
}
break;
case ZEND_INIT_FCALL:
@@ -477,6 +496,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
}
break;
case ZEND_ASSIGN_OBJ:
+ case ZEND_ASSIGN_OBJ_REF:
case ZEND_FETCH_OBJ_R:
case ZEND_FETCH_OBJ_W:
case ZEND_FETCH_OBJ_RW:
@@ -490,12 +510,12 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
case ZEND_POST_DEC_OBJ:
TO_STRING_NOWARN(val);
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
- opline->extended_value = alloc_cache_slots(op_array, 2);
+ opline->extended_value = alloc_cache_slots(op_array, 3);
break;
case ZEND_ISSET_ISEMPTY_PROP_OBJ:
TO_STRING_NOWARN(val);
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
- opline->extended_value = alloc_cache_slots(op_array, 2) | (opline->extended_value & ZEND_ISEMPTY);
+ opline->extended_value = alloc_cache_slots(op_array, 3) | (opline->extended_value & ZEND_ISEMPTY);
break;
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
@@ -512,7 +532,9 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
if (opline->extended_value == ZEND_ASSIGN_OBJ) {
TO_STRING_NOWARN(val);
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
- (opline+1)->extended_value = alloc_cache_slots(op_array, 2);
+ (opline+1)->extended_value = alloc_cache_slots(op_array, 3);
+ } else if (opline->extended_value == ZEND_ASSIGN_STATIC_PROP) {
+ goto handle_static_prop;
} else if (opline->extended_value == ZEND_ASSIGN_DIM) {
if (Z_TYPE_P(val) == IS_STRING) {
zend_ulong index;
diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c
index ea387bb95f..ad34e7f643 100644
--- a/ext/opcache/Optimizer/zend_ssa.c
+++ b/ext/opcache/Optimizer/zend_ssa.c
@@ -642,6 +642,22 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags,
//NEW_SSA_VAR(next->op1.var)
}
break;
+ case ZEND_ASSIGN_OBJ_REF:
+ if (opline->op1_type == IS_CV) {
+ ssa_ops[k].op1_def = ssa_vars_count;
+ var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count;
+ ssa_vars_count++;
+ //NEW_SSA_VAR(opline->op1.var)
+ }
+ /* break missing intentionally */
+ case ZEND_ASSIGN_STATIC_PROP_REF:
+ if (next->op1_type == IS_CV) {
+ ssa_ops[k + 1].op1_def = ssa_vars_count;
+ var[EX_VAR_TO_NUM(next->op1.var)] = ssa_vars_count;
+ ssa_vars_count++;
+ //NEW_SSA_VAR(next->op1.var)
+ }
+ break;
case ZEND_PRE_INC_OBJ:
case ZEND_PRE_DEC_OBJ:
case ZEND_POST_INC_OBJ:
diff --git a/ext/opcache/tests/opt/prop_types.phpt b/ext/opcache/tests/opt/prop_types.phpt
new file mode 100644
index 0000000000..7962b1b893
--- /dev/null
+++ b/ext/opcache/tests/opt/prop_types.phpt
@@ -0,0 +1,115 @@
+--TEST--
+Property types in inference
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.opt_debug_level=0x200000
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+class Test {
+ public bool $public;
+ protected int $protected;
+ private float $private;
+
+ public function inTest() {
+ var_dump($this->public, $this->protected, $this->private);
+ }
+
+ public function inTestWithTest2(Test2 $test2) {
+ var_dump($test2->public, $test2->protected, $test2->private);
+ }
+}
+
+class Test2 extends Test {
+ private array $private;
+
+ public function inTest2() {
+ var_dump($this->public, $this->protected, $this->private);
+ }
+}
+
+function noScope(Test $test) {
+ var_dump($test->public, $test->protected, $test->private);
+}
+
+?>
+--EXPECTF--
+$_main: ; (lines=1, args=0, vars=0, tmps=0, ssa_vars=0, no_loops)
+ ; (before dfa pass)
+ ; %s
+ ; return [long] RANGE[1..1]
+BB0: start exit lines=[0-0]
+ ; level=0
+ RETURN int(1)
+
+noScope: ; (lines=10, args=1, vars=1, tmps=1, ssa_vars=5, no_loops)
+ ; (before dfa pass)
+ ; %s
+ ; return [null] RANGE[0..0]
+ ; #0.CV0($test) NOVAL [undef]
+BB0: start exit lines=[0-9]
+ ; level=0
+ #1.CV0($test) [object (instanceof Test)] = RECV 1
+ INIT_FCALL 3 128 string("var_dump")
+ #2.T1 [bool] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("public")
+ SEND_VAL #2.T1 [bool] 1
+ #3.T1 [any] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("protected")
+ SEND_VAL #3.T1 [any] 2
+ #4.T1 [any] = FETCH_OBJ_R #1.CV0($test) [object (instanceof Test)] string("private")
+ SEND_VAL #4.T1 [any] 3
+ DO_ICALL
+ RETURN null
+
+Test::inTest: ; (lines=9, args=0, vars=0, tmps=1, ssa_vars=3, no_loops)
+ ; (before dfa pass)
+ ; %s
+ ; return [null] RANGE[0..0]
+BB0: start exit lines=[0-8]
+ ; level=0
+ INIT_FCALL 3 128 string("var_dump")
+ #0.T0 [bool] = FETCH_OBJ_R THIS string("public")
+ SEND_VAL #0.T0 [bool] 1
+ #1.T0 [long] = FETCH_OBJ_R THIS string("protected")
+ SEND_VAL #1.T0 [long] 2
+ #2.T0 [double] = FETCH_OBJ_R THIS string("private")
+ SEND_VAL #2.T0 [double] 3
+ DO_ICALL
+ RETURN null
+
+Test::inTestWithTest2: ; (lines=10, args=1, vars=1, tmps=1, ssa_vars=5, no_loops)
+ ; (before dfa pass)
+ ; %s
+ ; return [null] RANGE[0..0]
+ ; #0.CV0($test2) NOVAL [undef]
+BB0: start exit lines=[0-9]
+ ; level=0
+ #1.CV0($test2) [object (instanceof Test2)] = RECV 1
+ INIT_FCALL 3 128 string("var_dump")
+ #2.T1 [bool] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("public")
+ SEND_VAL #2.T1 [bool] 1
+ #3.T1 [long] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("protected")
+ SEND_VAL #3.T1 [long] 2
+ #4.T1 [double] = FETCH_OBJ_R #1.CV0($test2) [object (instanceof Test2)] string("private")
+ SEND_VAL #4.T1 [double] 3
+ DO_ICALL
+ RETURN null
+
+Test2::inTest2: ; (lines=9, args=0, vars=0, tmps=1, ssa_vars=3, no_loops)
+ ; (before dfa pass)
+ ; %s
+ ; return [null] RANGE[0..0]
+BB0: start exit lines=[0-8]
+ ; level=0
+ INIT_FCALL 3 128 string("var_dump")
+ #0.T0 [bool] = FETCH_OBJ_R THIS string("public")
+ SEND_VAL #0.T0 [bool] 1
+ #1.T0 [long] = FETCH_OBJ_R THIS string("protected")
+ SEND_VAL #1.T0 [long] 2
+ #2.T0 [array of [any, ref]] = FETCH_OBJ_R THIS string("private")
+ SEND_VAL #2.T0 [array of [any, ref]] 3
+ DO_ICALL
+ RETURN null
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index d22cc7ffd7..7b04d0d2df 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -232,6 +232,14 @@ static void zend_hash_clone_prop_info(HashTable *ht)
if (IN_ARENA(prop_info->ce)) {
prop_info->ce = ARENA_REALLOC(prop_info->ce);
}
+
+ if (ZEND_TYPE_IS_CE(prop_info->type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE(prop_info->type);
+ if (IN_ARENA(ce)) {
+ ce = ARENA_REALLOC(ce);
+ prop_info->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop_info->type));
+ }
+ }
}
}
}
@@ -304,6 +312,16 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
/* constants table */
zend_hash_clone_constants(&ce->constants_table);
+ if (ce->properties_info_table) {
+ int i;
+ ce->properties_info_table = ARENA_REALLOC(ce->properties_info_table);
+ for (i = 0; i < ce->default_properties_count; i++) {
+ if (IN_ARENA(ce->properties_info_table[i])) {
+ ce->properties_info_table[i] = ARENA_REALLOC(ce->properties_info_table[i]);
+ }
+ }
+ }
+
if (ce->num_interfaces) {
zend_class_name *interface_names;
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 86cb8a2e25..92a77ab792 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -577,6 +577,17 @@ static void zend_file_cache_serialize_prop_info(zval *zv,
SERIALIZE_STR(prop->doc_comment);
}
}
+ if (prop->type) {
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ zend_string *name = ZEND_TYPE_NAME(prop->type);
+ SERIALIZE_STR(name);
+ prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type));
+ } else if (ZEND_TYPE_IS_CE(prop->type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
+ SERIALIZE_PTR(ce);
+ prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
+ }
+ }
}
}
@@ -660,6 +671,19 @@ static void zend_file_cache_serialize_class(zval *zv,
SERIALIZE_STR(ce->info.user.doc_comment);
zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
+ if (ce->properties_info_table) {
+ uint32_t i;
+ zend_property_info **table;
+
+ SERIALIZE_PTR(ce->properties_info_table);
+ table = ce->properties_info_table;
+ UNSERIALIZE_PTR(table);
+
+ for (i = 0; i < ce->default_properties_count; i++) {
+ SERIALIZE_PTR(table[i]);
+ }
+ }
+
if (ce->num_interfaces) {
uint32_t i;
zend_class_name *interface_names;
@@ -1246,6 +1270,17 @@ static void zend_file_cache_unserialize_prop_info(zval *zv,
UNSERIALIZE_STR(prop->doc_comment);
}
}
+ if (prop->type) {
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ zend_string *name = ZEND_TYPE_NAME(prop->type);
+ UNSERIALIZE_STR(name);
+ prop->type = ZEND_TYPE_ENCODE_CLASS(name, ZEND_TYPE_ALLOW_NULL(prop->type));
+ } else if (ZEND_TYPE_IS_CE(prop->type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
+ UNSERIALIZE_PTR(ce);
+ prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
+ }
+ }
}
}
@@ -1325,6 +1360,15 @@ static void zend_file_cache_unserialize_class(zval *zv,
zend_file_cache_unserialize_hash(&ce->properties_info,
script, buf, zend_file_cache_unserialize_prop_info, NULL);
+ if (ce->properties_info_table) {
+ uint32_t i;
+ UNSERIALIZE_PTR(ce->properties_info_table);
+
+ for (i = 0; i < ce->default_properties_count; i++) {
+ UNSERIALIZE_PTR(ce->properties_info_table[i]);
+ }
+ }
+
if (ce->num_interfaces) {
uint32_t i;
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index eba9dd23e4..af9244bbf5 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -746,6 +746,16 @@ static void zend_persist_property_info(zval *zv)
prop->doc_comment = NULL;
}
}
+
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ zend_string *class_name = ZEND_TYPE_NAME(prop->type);
+ zend_accel_store_interned_string(class_name);
+ prop->type = ZEND_TYPE_ENCODE_CLASS(class_name, ZEND_TYPE_ALLOW_NULL(prop->type));
+ } else if (ZEND_TYPE_IS_CE(prop->type)) {
+ zend_class_entry *ce = ZEND_TYPE_CE(prop->type);
+ ce = zend_shared_alloc_get_xlat_entry(ce);
+ prop->type = ZEND_TYPE_ENCODE_CE(ce, ZEND_TYPE_ALLOW_NULL(prop->type));
+ }
}
static void zend_persist_class_constant(zval *zv)
@@ -786,6 +796,16 @@ static void zend_persist_class_constant(zval *zv)
}
}
+static zend_bool has_unresolved_property_types(zend_class_entry *ce) {
+ zend_property_info *prop;
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ return 1;
+ }
+ } ZEND_HASH_FOREACH_END();
+ return 0;
+}
+
static void zend_persist_class_entry(zval *zv)
{
zend_class_entry *ce = Z_PTR_P(zv);
@@ -793,6 +813,7 @@ static void zend_persist_class_entry(zval *zv)
if (ce->type == ZEND_USER_CLASS) {
if ((ce->ce_flags & ZEND_ACC_LINKED)
&& (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)
+ && !has_unresolved_property_types(ce)
&& !ZCG(current_persistent_script)->corrupted) {
ZCG(is_immutable_class) = 1;
ce = Z_PTR_P(zv) = zend_shared_memdup_put(ce, sizeof(zend_class_entry));
@@ -855,6 +876,19 @@ static void zend_persist_class_entry(zval *zv)
zend_hash_persist(&ce->properties_info, zend_persist_property_info);
HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
+ if (ce->properties_info_table) {
+ int i;
+
+ size_t size = sizeof(zend_property_info *) * ce->default_properties_count;
+ memcpy(ZCG(arena_mem), ce->properties_info_table, size);
+ ce->properties_info_table = ZCG(arena_mem);
+ ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(size));
+
+ for (i = 0; i < ce->default_properties_count; i++) {
+ ce->properties_info_table[i] = zend_shared_alloc_get_xlat_entry(ce->properties_info_table[i]);
+ }
+ }
+
if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_LINKED)) {
uint32_t i = 0;
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 5fd48a224e..a17d7c4627 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -306,6 +306,11 @@ static void zend_persist_property_info_calc(zval *zv)
zend_shared_alloc_register_xlat_entry(prop, prop);
ADD_SIZE_EX(sizeof(zend_property_info));
ADD_INTERNED_STRING(prop->name);
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ zend_string *class_name = ZEND_TYPE_NAME(prop->type);
+ ADD_INTERNED_STRING(class_name);
+ prop->type = ZEND_TYPE_ENCODE_CLASS(class_name, ZEND_TYPE_ALLOW_NULL(prop->type));
+ }
if (ZCG(accel_directives).save_comments && prop->doc_comment) {
ADD_STRING(prop->doc_comment);
}
@@ -326,6 +331,16 @@ static void zend_persist_class_constant_calc(zval *zv)
}
}
+static zend_bool has_unresolved_property_types(zend_class_entry *ce) {
+ zend_property_info *prop;
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
+ if (ZEND_TYPE_IS_NAME(prop->type)) {
+ return 1;
+ }
+ } ZEND_HASH_FOREACH_END();
+ return 0;
+}
+
static void zend_persist_class_entry_calc(zval *zv)
{
zend_class_entry *ce = Z_PTR_P(zv);
@@ -334,6 +349,7 @@ static void zend_persist_class_entry_calc(zval *zv)
ZCG(is_immutable_class) =
(ce->ce_flags & ZEND_ACC_LINKED) &&
(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) &&
+ !has_unresolved_property_types(ce) &&
!ZCG(current_persistent_script)->corrupted;
ADD_SIZE_EX(sizeof(zend_class_entry));
@@ -371,6 +387,10 @@ static void zend_persist_class_entry_calc(zval *zv)
zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc);
+ if (ce->properties_info_table) {
+ ADD_ARENA_SIZE(sizeof(zend_property_info *) * ce->default_properties_count);
+ }
+
if (ce->num_interfaces) {
uint32_t i;
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index e97cd8fda6..115801a380 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -2101,7 +2101,7 @@ PHP_FUNCTION(openssl_x509_export)
zend_bool notext = 1;
BIO * bio_out;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz/|b", &zcert, &zout, &notext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|b", &zcert, &zout, &notext) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -2123,9 +2123,8 @@ PHP_FUNCTION(openssl_x509_export)
if (PEM_write_bio_X509(bio_out, cert)) {
BUF_MEM *bio_buf;
- zval_ptr_dtor(zout);
BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length);
+ ZEND_TRY_ASSIGN_STRINGL(zout, bio_buf->data, bio_buf->length);
RETVAL_TRUE;
} else {
@@ -2925,7 +2924,7 @@ PHP_FUNCTION(openssl_pkcs12_export)
zval * item;
STACK_OF(X509) *ca = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz/zs|a", &zcert, &zout, &zpkey, &pass, &pass_len, &args) == FAILURE)
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzzs|a", &zcert, &zout, &zpkey, &pass, &pass_len, &args) == FAILURE)
return;
RETVAL_FALSE;
@@ -2965,9 +2964,8 @@ PHP_FUNCTION(openssl_pkcs12_export)
if (i2d_PKCS12_bio(bio_out, p12)) {
BUF_MEM *bio_buf;
- zval_ptr_dtor(zout);
BIO_get_mem_ptr(bio_out, &bio_buf);
- ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length);
+ ZEND_TRY_ASSIGN_STRINGL(zout, bio_buf->data, bio_buf->length);
RETVAL_TRUE;
} else {
@@ -3006,7 +3004,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
BIO * bio_in = NULL;
int i;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/s", &zp12, &zp12_len, &zout, &pass, &pass_len) == FAILURE)
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szs", &zp12, &zp12_len, &zout, &pass, &pass_len) == FAILURE)
return;
RETVAL_FALSE;
@@ -3024,8 +3022,10 @@ PHP_FUNCTION(openssl_pkcs12_read)
BIO * bio_out;
int cert_num;
- zval_ptr_dtor(zout);
- array_init(zout);
+ zout = zend_try_array_init(zout);
+ if (!zout) {
+ goto cleanup;
+ }
if (cert) {
bio_out = BIO_new(BIO_s_mem());
@@ -3380,7 +3380,7 @@ PHP_FUNCTION(openssl_csr_export)
BIO * bio_out;
zend_resource *csr_resource;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|b", &zcsr, &zout, &notext) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|b", &zcsr, &zout, &notext) == FAILURE) {
return;
}
@@ -3403,8 +3403,7 @@ PHP_FUNCTION(openssl_csr_export)
BUF_MEM *bio_buf;
BIO_get_mem_ptr(bio_out, &bio_buf);
- zval_ptr_dtor(zout);
- ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length);
+ ZEND_TRY_ASSIGN_STRINGL(zout, bio_buf->data, bio_buf->length);
RETVAL_TRUE;
} else {
@@ -3573,7 +3572,7 @@ PHP_FUNCTION(openssl_csr_new)
int we_made_the_key = 1;
zend_resource *key_resource;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "az/|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "az|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -3581,9 +3580,12 @@ PHP_FUNCTION(openssl_csr_new)
PHP_SSL_REQ_INIT(&req);
if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
+ zval *out_pkey_val = out_pkey;
+ ZVAL_DEREF(out_pkey_val);
+
/* Generate or use a private key */
- if (Z_TYPE_P(out_pkey) != IS_NULL) {
- req.priv_key = php_openssl_evp_from_zval(out_pkey, 0, NULL, 0, 0, &key_resource);
+ if (Z_TYPE_P(out_pkey_val) != IS_NULL) {
+ req.priv_key = php_openssl_evp_from_zval(out_pkey_val, 0, NULL, 0, 0, &key_resource);
if (req.priv_key != NULL) {
we_made_the_key = 0;
}
@@ -3621,8 +3623,7 @@ PHP_FUNCTION(openssl_csr_new)
if (we_made_the_key) {
/* and a resource for the private key */
- zval_ptr_dtor(out_pkey);
- ZVAL_RES(out_pkey, zend_register_resource(req.priv_key, le_key));
+ ZEND_TRY_ASSIGN_RES(out_pkey, zend_register_resource(req.priv_key, le_key));
req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */
} else if (key_resource != NULL) {
req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */
@@ -4633,7 +4634,7 @@ PHP_FUNCTION(openssl_pkey_export)
BIO * bio_out = NULL;
const EVP_CIPHER * cipher;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz/|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -4685,8 +4686,7 @@ PHP_FUNCTION(openssl_pkey_export)
RETVAL_TRUE;
bio_mem_len = BIO_get_mem_data(bio_out, &bio_mem_ptr);
- zval_ptr_dtor(out);
- ZVAL_STRINGL(out, bio_mem_ptr, bio_mem_len);
+ ZEND_TRY_ASSIGN_STRINGL(out, bio_mem_ptr, bio_mem_len);
} else {
php_openssl_store_errors();
}
@@ -5389,7 +5389,7 @@ PHP_FUNCTION(openssl_pkcs7_read)
PKCS7 * p7 = NULL;
int i;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/", &p7b, &p7b_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &p7b, &p7b_len,
&zout) == FAILURE) {
return;
}
@@ -5431,8 +5431,10 @@ PHP_FUNCTION(openssl_pkcs7_read)
break;
}
- zval_ptr_dtor(zout);
- array_init(zout);
+ zout = zend_try_array_init(zout);
+ if (!zout) {
+ goto clean_exit;
+ }
if (certs != NULL) {
for (i = 0; i < sk_X509_num(certs); i++) {
@@ -5686,7 +5688,7 @@ PHP_FUNCTION(openssl_private_encrypt)
size_t data_len;
zend_long padding = RSA_PKCS1_PADDING;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -5717,9 +5719,8 @@ PHP_FUNCTION(openssl_private_encrypt)
}
if (successful) {
- zval_ptr_dtor(crypted);
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
- ZVAL_NEW_STR(crypted, cryptedbuf);
+ ZEND_TRY_ASSIGN_NEW_STR(crypted, cryptedbuf);
cryptedbuf = NULL;
RETVAL_TRUE;
} else {
@@ -5749,7 +5750,7 @@ PHP_FUNCTION(openssl_private_decrypt)
char * data;
size_t data_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -5786,9 +5787,8 @@ PHP_FUNCTION(openssl_private_decrypt)
efree(crypttemp);
if (successful) {
- zval_ptr_dtor(crypted);
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
- ZVAL_NEW_STR(crypted, cryptedbuf);
+ ZEND_TRY_ASSIGN_NEW_STR(crypted, cryptedbuf);
cryptedbuf = NULL;
RETVAL_TRUE;
} else {
@@ -5818,7 +5818,7 @@ PHP_FUNCTION(openssl_public_encrypt)
char * data;
size_t data_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE)
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE)
return;
RETVAL_FALSE;
@@ -5848,9 +5848,8 @@ PHP_FUNCTION(openssl_public_encrypt)
}
if (successful) {
- zval_ptr_dtor(crypted);
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
- ZVAL_NEW_STR(crypted, cryptedbuf);
+ ZEND_TRY_ASSIGN_NEW_STR(crypted, cryptedbuf);
cryptedbuf = NULL;
RETVAL_TRUE;
} else {
@@ -5880,7 +5879,7 @@ PHP_FUNCTION(openssl_public_decrypt)
char * data;
size_t data_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
return;
}
RETVAL_FALSE;
@@ -5919,9 +5918,8 @@ PHP_FUNCTION(openssl_public_decrypt)
efree(crypttemp);
if (successful) {
- zval_ptr_dtor(crypted);
ZSTR_VAL(cryptedbuf)[cryptedlen] = '\0';
- ZVAL_NEW_STR(crypted, cryptedbuf);
+ ZEND_TRY_ASSIGN_NEW_STR(crypted, cryptedbuf);
cryptedbuf = NULL;
RETVAL_TRUE;
} else {
@@ -5982,7 +5980,7 @@ PHP_FUNCTION(openssl_sign)
zend_long signature_algo = OPENSSL_ALGO_SHA1;
const EVP_MD *mdtype;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z|z", &data, &data_len, &signature, &key, &method) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|z", &data, &data_len, &signature, &key, &method) == FAILURE) {
return;
}
pkey = php_openssl_evp_from_zval(key, 0, "", 0, 0, &keyresource);
@@ -6015,10 +6013,9 @@ PHP_FUNCTION(openssl_sign)
EVP_SignInit(md_ctx, mdtype) &&
EVP_SignUpdate(md_ctx, data, data_len) &&
EVP_SignFinal(md_ctx, (unsigned char*)ZSTR_VAL(sigbuf), &siglen, pkey)) {
- zval_ptr_dtor(signature);
ZSTR_VAL(sigbuf)[siglen] = '\0';
ZSTR_LEN(sigbuf) = siglen;
- ZVAL_NEW_STR(signature, sigbuf);
+ ZEND_TRY_ASSIGN_NEW_STR(signature, sigbuf);
RETVAL_TRUE;
} else {
php_openssl_store_errors();
@@ -6110,7 +6107,7 @@ PHP_FUNCTION(openssl_seal)
const EVP_CIPHER *cipher;
EVP_CIPHER_CTX *ctx;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z/a|sz/", &data, &data_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szza|sz", &data, &data_len,
&sealdata, &ekeys, &pubkeys, &method, &method_len, &iv) == FAILURE) {
return;
}
@@ -6184,12 +6181,15 @@ PHP_FUNCTION(openssl_seal)
}
if (len1 + len2 > 0) {
- zval_ptr_dtor(sealdata);
- ZVAL_NEW_STR(sealdata, zend_string_init((char*)buf, len1 + len2, 0));
+ ZEND_TRY_ASSIGN_NEW_STR(sealdata, zend_string_init((char*)buf, len1 + len2, 0));
efree(buf);
- zval_ptr_dtor(ekeys);
- array_init(ekeys);
+ ekeys = zend_try_array_init(ekeys);
+ if (!ekeys) {
+ EVP_CIPHER_CTX_free(ctx);
+ goto clean_exit;
+ }
+
for (i=0; i<nkeys; i++) {
eks[i][eksl[i]] = '\0';
add_next_index_stringl(ekeys, (const char*)eks[i], eksl[i]);
@@ -6198,9 +6198,8 @@ PHP_FUNCTION(openssl_seal)
}
if (iv) {
- zval_ptr_dtor(iv);
iv_buf[iv_len] = '\0';
- ZVAL_NEW_STR(iv, zend_string_init((char*)iv_buf, iv_len, 0));
+ ZEND_TRY_ASSIGN_NEW_STR(iv, zend_string_init((char*)iv_buf, iv_len, 0));
}
} else {
efree(buf);
@@ -6242,7 +6241,7 @@ PHP_FUNCTION(openssl_open)
size_t method_len = 0, iv_len = 0;
const EVP_CIPHER *cipher;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/sz|ss", &data, &data_len, &opendata,
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szsz|ss", &data, &data_len, &opendata,
&ekey, &ekey_len, &privkey, &method, &method_len, &iv, &iv_len) == FAILURE) {
return;
}
@@ -6288,9 +6287,8 @@ PHP_FUNCTION(openssl_open)
if (ctx != NULL && EVP_OpenInit(ctx, cipher, (unsigned char *)ekey, (int)ekey_len, iv_buf, pkey) &&
EVP_OpenUpdate(ctx, buf, &len1, (unsigned char *)data, (int)data_len) &&
EVP_OpenFinal(ctx, buf + len1, &len2) && (len1 + len2 > 0)) {
- zval_ptr_dtor(opendata);
buf[len1 + len2] = '\0';
- ZVAL_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0));
+ ZEND_TRY_ASSIGN_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0));
RETVAL_TRUE;
} else {
php_openssl_store_errors();
@@ -6642,7 +6640,7 @@ PHP_FUNCTION(openssl_encrypt)
zend_string *outbuf;
zend_bool free_iv = 0, free_password = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lsz/sl", &data, &data_len, &method, &method_len,
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lszsl", &data, &data_len, &method, &method_len,
&password, &password_len, &options, &iv, &iv_len, &tag, &aad, &aad_len, &tag_len) == FAILURE) {
return;
}
@@ -6689,10 +6687,9 @@ PHP_FUNCTION(openssl_encrypt)
zend_string *tag_str = zend_string_alloc(tag_len, 0);
if (EVP_CIPHER_CTX_ctrl(cipher_ctx, mode.aead_get_tag_flag, tag_len, ZSTR_VAL(tag_str)) == 1) {
- zval_ptr_dtor(tag);
ZSTR_VAL(tag_str)[tag_len] = '\0';
ZSTR_LEN(tag_str) = tag_len;
- ZVAL_NEW_STR(tag, tag_str);
+ ZEND_TRY_ASSIGN_NEW_STR(tag, tag_str);
} else {
php_error_docref(NULL, E_WARNING, "Retrieving verification tag failed");
zend_string_release_ex(tag_str, 0);
@@ -6700,8 +6697,7 @@ PHP_FUNCTION(openssl_encrypt)
RETVAL_FALSE;
}
} else if (tag) {
- zval_ptr_dtor(tag);
- ZVAL_NULL(tag);
+ ZEND_TRY_ASSIGN_NULL(tag);
php_error_docref(NULL, E_WARNING,
"The authenticated tag cannot be provided for cipher that doesn not support AEAD");
} else if (mode.is_aead) {
@@ -6848,13 +6844,12 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
zend_string *buffer = NULL;
zval *zstrong_result_returned = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z/", &buffer_length, &zstrong_result_returned) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
return;
}
if (zstrong_result_returned) {
- zval_ptr_dtor(zstrong_result_returned);
- ZVAL_FALSE(zstrong_result_returned);
+ ZEND_TRY_ASSIGN_FALSE(zstrong_result_returned);
}
if (buffer_length <= 0
@@ -6872,7 +6867,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
if (php_win32_get_random_bytes((unsigned char*)buffer->val, (size_t) buffer_length) == FAILURE){
zend_string_release_ex(buffer, 0);
if (zstrong_result_returned) {
- ZVAL_FALSE(zstrong_result_returned);
+ ZEND_TRY_ASSIGN_FALSE(zstrong_result_returned);
}
zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
return;
@@ -6885,7 +6880,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
if (RAND_bytes((unsigned char*)ZSTR_VAL(buffer), (int)buffer_length) <= 0) {
zend_string_release_ex(buffer, 0);
if (zstrong_result_returned) {
- ZVAL_FALSE(zstrong_result_returned);
+ ZEND_TRY_ASSIGN_FALSE(zstrong_result_returned);
}
zend_throw_exception(zend_ce_exception, "Error reading from source device", 0);
return;
@@ -6898,7 +6893,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
RETVAL_NEW_STR(buffer);
if (zstrong_result_returned) {
- ZVAL_BOOL(zstrong_result_returned, 1);
+ ZEND_TRY_ASSIGN_TRUE(zstrong_result_returned);
}
}
/* }}} */
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index b243b22027..cf53edc7f6 100644
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -663,7 +663,7 @@ PHP_FUNCTION(pcntl_waitpid)
struct rusage rusage;
#endif
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/|lz/", &pid, &z_status, &options, &z_rusage) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz|lz", &pid, &z_status, &options, &z_rusage) == FAILURE) {
return;
}
@@ -671,11 +671,9 @@ PHP_FUNCTION(pcntl_waitpid)
#ifdef HAVE_WAIT4
if (z_rusage) {
- if (Z_TYPE_P(z_rusage) != IS_ARRAY) {
- zval_ptr_dtor(z_rusage);
- array_init(z_rusage);
- } else {
- zend_hash_clean(Z_ARRVAL_P(z_rusage));
+ z_rusage = zend_try_array_init(z_rusage);
+ if (!z_rusage) {
+ return;
}
memset(&rusage, 0, sizeof(struct rusage));
@@ -697,8 +695,7 @@ PHP_FUNCTION(pcntl_waitpid)
}
#endif
- zval_ptr_dtor(z_status);
- ZVAL_LONG(z_status, status);
+ ZEND_TRY_ASSIGN_LONG(z_status, status);
RETURN_LONG((zend_long) child_id);
}
@@ -716,18 +713,16 @@ PHP_FUNCTION(pcntl_wait)
struct rusage rusage;
#endif
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/|lz/", &z_status, &options, &z_rusage) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|lz", &z_status, &options, &z_rusage) == FAILURE) {
return;
}
status = zval_get_long(z_status);
#ifdef HAVE_WAIT3
if (z_rusage) {
- if (Z_TYPE_P(z_rusage) != IS_ARRAY) {
- zval_ptr_dtor(z_rusage);
- array_init(z_rusage);
- } else {
- zend_hash_clean(Z_ARRVAL_P(z_rusage));
+ z_rusage = zend_try_array_init(z_rusage);
+ if (!z_rusage) {
+ return;
}
memset(&rusage, 0, sizeof(struct rusage));
@@ -750,8 +745,7 @@ PHP_FUNCTION(pcntl_wait)
}
#endif
- zval_ptr_dtor(z_status);
- ZVAL_LONG(z_status, status);
+ ZEND_TRY_ASSIGN_LONG(z_status, status);
RETURN_LONG((zend_long) child_id);
}
@@ -1105,7 +1099,7 @@ PHP_FUNCTION(pcntl_sigprocmask)
zval *user_set, *user_oldset = NULL, *user_signo;
sigset_t set, oldset;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "la|z/", &how, &user_set, &user_oldset) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "la|z", &how, &user_set, &user_oldset) == FAILURE) {
return;
}
@@ -1131,12 +1125,11 @@ PHP_FUNCTION(pcntl_sigprocmask)
}
if (user_oldset != NULL) {
- if (Z_TYPE_P(user_oldset) != IS_ARRAY) {
- zval_ptr_dtor(user_oldset);
- array_init(user_oldset);
- } else {
- zend_hash_clean(Z_ARRVAL_P(user_oldset));
+ user_oldset = zend_try_array_init(user_oldset);
+ if (!user_oldset) {
+ return;
}
+
for (signo = 1; signo < NSIG; ++signo) {
if (sigismember(&oldset, signo) != 1) {
continue;
@@ -1162,11 +1155,11 @@ static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{
struct timespec timeout;
if (timedwait) {
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z/ll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) {
return;
}
} else {
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z/", &user_set, &user_siginfo) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|z", &user_set, &user_siginfo) == FAILURE) {
return;
}
}
@@ -1230,12 +1223,11 @@ PHP_FUNCTION(pcntl_sigtimedwait)
static void pcntl_siginfo_to_zval(int signo, siginfo_t *siginfo, zval *user_siginfo) /* {{{ */
{
if (signo > 0 && user_siginfo) {
- if (Z_TYPE_P(user_siginfo) != IS_ARRAY) {
- zval_ptr_dtor(user_siginfo);
- array_init(user_siginfo);
- } else {
- zend_hash_clean(Z_ARRVAL_P(user_siginfo));
+ user_siginfo = zend_try_array_init(user_siginfo);
+ if (!user_siginfo) {
+ return;
}
+
add_assoc_long_ex(user_siginfo, "signo", sizeof("signo")-1, siginfo->si_signo);
add_assoc_long_ex(user_siginfo, "errno", sizeof("errno")-1, siginfo->si_errno);
add_assoc_long_ex(user_siginfo, "code", sizeof("code")-1, siginfo->si_code);
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index 16ebedd7ac..8622ea8c65 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -970,7 +970,7 @@ static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ *
Z_PARAM_STR(regex)
Z_PARAM_STR(subject)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(subpats)
+ Z_PARAM_ZVAL(subpats)
Z_PARAM_LONG(flags)
Z_PARAM_LONG(start_offset)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
@@ -1014,8 +1014,10 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, size_t sub
/* Overwrite the passed-in value for subpatterns with an empty array. */
if (subpats != NULL) {
- zval_ptr_dtor(subpats);
- array_init(subpats);
+ subpats = zend_try_array_init(subpats);
+ if (!subpats) {
+ return;
+ }
}
subpats_order = global ? PREG_PATTERN_ORDER : 0;
@@ -2239,7 +2241,7 @@ static void preg_replace_common(INTERNAL_FUNCTION_PARAMETERS, int is_filter)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(limit)
- Z_PARAM_ZVAL_DEREF(zcount)
+ Z_PARAM_ZVAL(zcount)
ZEND_PARSE_PARAMETERS_END();
if (Z_TYPE_P(replace) != IS_ARRAY) {
@@ -2305,8 +2307,7 @@ static void preg_replace_common(INTERNAL_FUNCTION_PARAMETERS, int is_filter)
}
if (zcount) {
- zval_ptr_dtor(zcount);
- ZVAL_LONG(zcount, replace_count);
+ ZEND_TRY_ASSIGN_LONG(zcount, replace_count);
}
}
/* }}} */
@@ -2336,7 +2337,7 @@ static PHP_FUNCTION(preg_replace_callback)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(limit)
- Z_PARAM_ZVAL_DEREF(zcount)
+ Z_PARAM_ZVAL(zcount)
ZEND_PARSE_PARAMETERS_END();
if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
@@ -2353,8 +2354,7 @@ static PHP_FUNCTION(preg_replace_callback)
replace_count = preg_replace_func_impl(return_value, regex, &fci, &fcc, subject, limit);
if (zcount) {
- zval_ptr_dtor(zcount);
- ZVAL_LONG(zcount, replace_count);
+ ZEND_TRY_ASSIGN_LONG(zcount, replace_count);
}
}
/* }}} */
@@ -2376,7 +2376,7 @@ static PHP_FUNCTION(preg_replace_callback_array)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(limit)
- Z_PARAM_ZVAL_DEREF(zcount)
+ Z_PARAM_ZVAL(zcount)
ZEND_PARSE_PARAMETERS_END();
fci.size = sizeof(fci);
@@ -2421,8 +2421,7 @@ static PHP_FUNCTION(preg_replace_callback_array)
} ZEND_HASH_FOREACH_END();
if (zcount) {
- zval_ptr_dtor(zcount);
- ZVAL_LONG(zcount, replace_count);
+ ZEND_TRY_ASSIGN_LONG(zcount, replace_count);
}
}
/* }}} */
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index 0b6fc90253..9355d3d3df 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -2176,7 +2176,7 @@ const zend_function_entry pdo_dbstmt_functions[] = {
};
/* {{{ overloaded handlers for PDOStatement class */
-static void dbstmt_prop_write(zval *object, zval *member, zval *value, void **cache_slot)
+static zval *dbstmt_prop_write(zval *object, zval *member, zval *value, void **cache_slot)
{
pdo_stmt_t *stmt = Z_PDO_STMT_P(object);
@@ -2184,8 +2184,9 @@ static void dbstmt_prop_write(zval *object, zval *member, zval *value, void **ca
if (strcmp(Z_STRVAL_P(member), "queryString") == 0) {
pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "property queryString is read only");
+ return value;
} else {
- zend_std_write_property(object, member, value, cache_slot);
+ return zend_std_write_property(object, member, value, cache_slot);
}
}
@@ -2499,9 +2500,10 @@ static zval *row_dim_read(zval *object, zval *member, int type, zval *rv)
return row_prop_read(object, member, type, NULL, rv);
}
-static void row_prop_write(zval *object, zval *member, zval *value, void **cache_slot)
+static zval *row_prop_write(zval *object, zval *member, zval *value, void **cache_slot)
{
php_error_docref(NULL, E_WARNING, "This PDORow is not from a writable result set");
+ return value;
}
static void row_dim_write(zval *object, zval *member, zval *value)
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 105a87da8b..323a4d2fa4 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -2855,8 +2855,10 @@ ZEND_METHOD(reflection_type, isBuiltin)
/* {{{ reflection_type_name */
static zend_string *reflection_type_name(type_reference *param) {
- if (ZEND_TYPE_IS_CLASS(param->type)) {
+ if (ZEND_TYPE_IS_NAME(param->type)) {
return zend_string_copy(ZEND_TYPE_NAME(param->type));
+ } else if (ZEND_TYPE_IS_CE(param->type)) {
+ return zend_string_copy(ZEND_TYPE_CE(param->type)->name);
} else {
char *name = zend_get_type_by_const(ZEND_TYPE_CODE(param->type));
return zend_string_init(name, strlen(name), 0);
@@ -3809,7 +3811,7 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
return;
}
- prop = zend_std_get_static_property(ce, name, 1);
+ prop = zend_std_get_static_property(ce, name, BP_VAR_IS);
if (!prop) {
if (def_value) {
ZVAL_COPY(return_value, def_value);
@@ -3830,6 +3832,7 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
{
reflection_object *intern;
zend_class_entry *ce;
+ zend_property_info *prop_info;
zend_string *name;
zval *variable_ptr, *value;
@@ -3842,15 +3845,30 @@ ZEND_METHOD(reflection_class, setStaticPropertyValue)
if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
return;
}
- variable_ptr = zend_std_get_static_property(ce, name, 1);
+ variable_ptr = zend_std_get_static_property_with_info(ce, name, BP_VAR_W, &prop_info);
if (!variable_ptr) {
+ zend_clear_exception();
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
return;
}
- ZVAL_DEREF(variable_ptr);
+
+ if (Z_ISREF_P(variable_ptr)) {
+ zend_reference *ref = Z_REF_P(variable_ptr);
+ variable_ptr = Z_REFVAL_P(variable_ptr);
+
+ if (!zend_verify_ref_assignable_zval(ref, value, 0)) {
+ return;
+ }
+ }
+
+ if (prop_info->type && !zend_verify_property_type(prop_info, value, 0)) {
+ return;
+ }
+
zval_ptr_dtor(variable_ptr);
ZVAL_COPY(variable_ptr, value);
+
}
/* }}} */
@@ -5463,6 +5481,55 @@ ZEND_METHOD(reflection_property, setValue)
}
/* }}} */
+/* {{{ proto public mixed ReflectionProperty::isInitialized([stdclass object])
+ Returns this property's value */
+ZEND_METHOD(reflection_property, isInitialized)
+{
+ reflection_object *intern;
+ property_reference *ref;
+ zval *object, *name;
+ zval *member_p = NULL;
+
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
+ name = _default_load_name(getThis());
+ zend_throw_exception_ex(reflection_exception_ptr, 0,
+ "Cannot access non-public member %s::$%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
+ return;
+ }
+
+ if (ref->prop.flags & ZEND_ACC_STATIC) {
+ member_p = zend_read_static_property_ex(intern->ce, ref->unmangled_name, 1);
+ if (member_p) {
+ RETURN_BOOL(!Z_ISUNDEF_P(member_p))
+ }
+ RETURN_FALSE;
+ } else {
+ zval name_zv;
+ zend_class_entry *old_scope;
+ int retval;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
+ return;
+ }
+
+ if (!instanceof_function(Z_OBJCE_P(object), ref->prop.ce)) {
+ _DO_THROW("Given object is not an instance of the class this property was declared in");
+ /* Returns from this function */
+ }
+
+ old_scope = EG(fake_scope);
+ EG(fake_scope) = intern->ce;
+ ZVAL_STR(&name_zv, ref->unmangled_name);
+ retval = Z_OBJ_HT_P(object)->has_property(object, &name_zv, ZEND_PROPERTY_EXISTS, NULL);
+ EG(fake_scope) = old_scope;
+
+ RETVAL_BOOL(retval);
+ }
+}
+/* }}} */
+
/* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
Get the declaring class */
ZEND_METHOD(reflection_property, getDeclaringClass)
@@ -5530,6 +5597,44 @@ ZEND_METHOD(reflection_property, setAccessible)
}
/* }}} */
+/* {{{ proto public ReflectionType ReflectionProperty::getType()
+ Returns the type associated with the property */
+ZEND_METHOD(reflection_property, getType)
+{
+ reflection_object *intern;
+ property_reference *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ if (!ZEND_TYPE_IS_SET(ref->prop.type)) {
+ RETURN_NULL();
+ }
+
+ reflection_type_factory(ref->prop.type, return_value);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionProperty::hasType()
+ Returns whether property has a type */
+ZEND_METHOD(reflection_property, hasType)
+{
+ reflection_object *intern;
+ property_reference *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ RETVAL_BOOL(ZEND_TYPE_IS_SET(ref->prop.type));
+}
+/* }}} */
+
/* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_extension, export)
@@ -6367,6 +6472,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_setValue, 0, 0, 1)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_isInitialized, 0, 0, 0)
+ ZEND_ARG_INFO(0, object)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
ZEND_ARG_INFO(0, visible)
ZEND_END_ARG_INFO()
@@ -6378,6 +6487,7 @@ static const zend_function_entry reflection_property_functions[] = {
ZEND_ME(reflection_property, getName, arginfo_reflection__void, 0)
ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
+ ZEND_ME(reflection_property, isInitialized, arginfo_reflection_property_isInitialized, 0)
ZEND_ME(reflection_property, isPublic, arginfo_reflection__void, 0)
ZEND_ME(reflection_property, isPrivate, arginfo_reflection__void, 0)
ZEND_ME(reflection_property, isProtected, arginfo_reflection__void, 0)
@@ -6387,6 +6497,8 @@ static const zend_function_entry reflection_property_functions[] = {
ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0)
ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
+ ZEND_ME(reflection_property, getType, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_property, hasType, arginfo_reflection__void, 0)
PHP_FE_END
};
@@ -6516,7 +6628,7 @@ static const zend_function_entry reflection_ext_functions[] = { /* {{{ */
}; /* }}} */
/* {{{ _reflection_write_property */
-static void _reflection_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+static zval *_reflection_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
if ((Z_TYPE_P(member) == IS_STRING)
&& zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STR_P(member))
@@ -6525,10 +6637,11 @@ static void _reflection_write_property(zval *object, zval *member, zval *value,
{
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Cannot set read-only property %s::$%s", ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member));
+ return &EG(uninitialized_zval);
}
else
{
- zend_std_write_property(object, member, value, cache_slot);
+ return zend_std_write_property(object, member, value, cache_slot);
}
}
/* }}} */
diff --git a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_002.phpt b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_002.phpt
index 14e8382e41..fb472681ca 100644
--- a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_002.phpt
+++ b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_002.phpt
@@ -1,5 +1,5 @@
--TEST--
-ReflectionClass::getStaticPropertyValue() - bad params
+ReflectionClass::setStaticPropertyValue() - bad params
--CREDITS--
Robin Fernandes <robinf@php.net>
Steve Seear <stevseea@php.net>
diff --git a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_003.phpt b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_003.phpt
new file mode 100644
index 0000000000..a83900a123
--- /dev/null
+++ b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_003.phpt
@@ -0,0 +1,39 @@
+--TEST--
+ReflectionClass::setStaticPropertyValue() - type constraints must be enforced
+--FILE--
+<?php
+
+class Test {
+ public static $x;
+ public static int $y = 2;
+}
+
+$rc = new ReflectionClass('Test');
+
+try {
+ $rc->setStaticPropertyValue("y", "foo");
+} catch (TypeError $e) { echo $e->getMessage(), "\n"; }
+var_dump(Test::$y);
+
+$rc->setStaticPropertyValue("y", "21");
+var_dump(Test::$y);
+
+
+Test::$x =& Test::$y;
+
+try {
+ $rc->setStaticPropertyValue("x", "foo");
+} catch (TypeError $e) { echo $e->getMessage(), "\n"; }
+var_dump(Test::$y);
+
+$rc->setStaticPropertyValue("x", "42");
+var_dump(Test::$y);
+
+?>
+--EXPECT--
+Typed property Test::$y must be int, string used
+int(2)
+int(21)
+Cannot assign string to reference held by property Test::$y of type int
+int(21)
+int(42)
diff --git a/ext/reflection/tests/ReflectionProperty_isInitialized.phpt b/ext/reflection/tests/ReflectionProperty_isInitialized.phpt
new file mode 100644
index 0000000000..f1f6e53ebd
--- /dev/null
+++ b/ext/reflection/tests/ReflectionProperty_isInitialized.phpt
@@ -0,0 +1,113 @@
+--TEST--
+Test ReflectionProperty::isInitialized()
+--FILE--
+<?php
+
+class A {
+ public static ?string $ssv = null;
+ public static ?string $ss;
+ public static $s;
+ public ?int $iv = null;
+ public ?int $i;
+ public $n;
+
+ private int $p;
+}
+
+class B extends A { }
+
+echo "Static properties:\n";
+var_dump((new ReflectionProperty(A::class, 'ssv'))->isInitialized());
+var_dump((new ReflectionProperty(A::class, 'ss'))->isInitialized());
+var_dump((new ReflectionProperty(A::class, 's'))->isInitialized());
+
+echo "Declared properties:\n";
+$a = new A;
+var_dump((new ReflectionProperty($a, 'iv'))->isInitialized($a));
+var_dump((new ReflectionProperty($a, 'i'))->isInitialized($a));
+var_dump((new ReflectionProperty($a, 'n'))->isInitialized($a));
+
+echo "Declared properties after unset:\n";
+unset($a->iv);
+unset($a->i);
+unset($a->n);
+var_dump((new ReflectionProperty($a, 'i'))->isInitialized($a));
+var_dump((new ReflectionProperty($a, 'iv'))->isInitialized($a));
+var_dump((new ReflectionProperty($a, 'n'))->isInitialized($a));
+
+echo "Dynamic properties:\n";
+$a->d = null;
+$rp = new ReflectionProperty($a, 'd');
+var_dump($rp->isInitialized($a));
+unset($a->d);
+var_dump($rp->isInitialized($a));
+
+echo "Visibility handling:\n";
+$rp = new ReflectionProperty('A', 'p');
+try {
+ var_dump($rp->isInitialized($a));
+} catch (ReflectionException $e) {
+ echo $e->getMessage(), "\n";
+}
+$rp->setAccessible(true);
+var_dump($rp->isInitialized($a));
+
+echo "Object type:\n";
+$rp = new ReflectionProperty('B', 'i');
+var_dump($rp->isInitialized($a));
+
+try {
+ var_dump($rp->isInitialized(new stdClass));
+} catch (ReflectionException $e) {
+ echo $e->getMessage(), "\n";
+}
+
+class WithMagic {
+ public $prop;
+ public int $intProp;
+
+ public function __isset($name) {
+ echo "__isset($name)\n";
+ return true;
+ }
+
+ public function __get($name) {
+ echo "__get($name)\n";
+ return "foobar";
+ }
+}
+
+echo "Class with __isset:\n";
+$obj = new WithMagic;
+unset($obj->prop);
+$rp = new ReflectionProperty('WithMagic', 'prop');
+var_dump($rp->isInitialized($obj));
+$rp = new ReflectionProperty('WithMagic', 'intProp');
+var_dump($rp->isInitialized($obj));
+
+?>
+--EXPECT--
+Static properties:
+bool(true)
+bool(false)
+bool(true)
+Declared properties:
+bool(true)
+bool(false)
+bool(true)
+Declared properties after unset:
+bool(false)
+bool(false)
+bool(false)
+Dynamic properties:
+bool(true)
+bool(false)
+Visibility handling:
+Cannot access non-public member A::$p
+bool(false)
+Object type:
+bool(false)
+Given object is not an instance of the class this property was declared in
+Class with __isset:
+bool(false)
+bool(false)
diff --git a/ext/reflection/tests/ReflectionProperty_typed_static.phpt b/ext/reflection/tests/ReflectionProperty_typed_static.phpt
new file mode 100644
index 0000000000..77f95d77ef
--- /dev/null
+++ b/ext/reflection/tests/ReflectionProperty_typed_static.phpt
@@ -0,0 +1,51 @@
+--TEST--
+ReflectionProperty::getValue() on typed static property
+--FILE--
+<?php
+
+class Test {
+ public static int $x = 42;
+ public static int $y;
+ public static $z;
+}
+
+$rp = new ReflectionProperty('Test', 'x');
+var_dump($rp->getValue());
+
+$rp = new ReflectionProperty('Test', 'y');
+try {
+ var_dump($rp->getValue());
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+
+$rp->setValue("24");
+var_dump($rp->getValue());
+
+try {
+ $rp->setValue("foo");
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($rp->getValue());
+
+Test::$z =& Test::$y;
+
+$rp = new ReflectionProperty('Test', 'z');
+try {
+ $rp->setValue("foo");
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($rp->getValue());
+
+
+?>
+--EXPECT--
+int(42)
+Typed static property Test::$y must not be accessed before initialization
+int(24)
+Typed property Test::$y must be int, string used
+int(24)
+Cannot assign string to reference held by property Test::$y of type int
+int(24)
diff --git a/ext/reflection/tests/ReflectionType_001.phpt b/ext/reflection/tests/ReflectionType_001.phpt
index d949e18107..e47a9615ba 100644
--- a/ext/reflection/tests/ReflectionType_001.phpt
+++ b/ext/reflection/tests/ReflectionType_001.phpt
@@ -74,6 +74,32 @@ foreach ([
}
}
+echo "\n*** property types\n";
+
+class PropTypeTest {
+ public int $int;
+ public string $string;
+ public array $arr;
+ public iterable $iterable;
+ public stdClass $std;
+ public OtherThing $other;
+ public $mixed;
+}
+
+$reflector = new ReflectionClass(PropTypeTest::class);
+
+foreach ($reflector->getProperties() as $name => $property) {
+ if ($property->hasType()) {
+ printf("public %s $%s;\n",
+ $property->getType(), $property->getName());
+ } else printf("public $%s;\n", $property->getName());
+}
+
+echo "*** resolved property types\n";
+$obj = new PropTypeTest;
+$obj->std = new stdClass;
+$r = (new ReflectionProperty($obj, 'std'))->getType();
+var_dump($r->getName());
?>
--EXPECT--
*** functions
@@ -185,3 +211,14 @@ bool(true)
bool(false)
bool(false)
string(4) "Test"
+
+*** property types
+public int $int;
+public string $string;
+public array $arr;
+public iterable $iterable;
+public stdClass $std;
+public OtherThing $other;
+public $mixed;
+*** resolved property types
+string(8) "stdClass"
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 15618244ff..49f2a8a7e6 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -415,7 +415,7 @@ static void change_node_zval(xmlNodePtr node, zval *value)
/* {{{ sxe_property_write()
*/
-static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool elements, zend_bool attribs, xmlNodePtr *pnewnode)
+static zval *sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool elements, zend_bool attribs, xmlNodePtr *pnewnode)
{
php_sxe_object *sxe;
xmlNodePtr node;
@@ -429,7 +429,6 @@ static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool
int test = 0;
int new_value = 0;
zend_long cnt = 0;
- int retval = SUCCESS;
zval tmp_zv, zval_copy;
zend_string *trim_str;
@@ -442,7 +441,7 @@ static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool
* and this is during runtime.
*/
zend_throw_error(NULL, "Cannot create unnamed attribute");
- return FAILURE;
+ return &EG(error_zval);
}
goto long_dim;
} else {
@@ -466,7 +465,7 @@ long_dim:
if (member == &tmp_zv) {
zval_ptr_dtor_str(&tmp_zv);
}
- return FAILURE;
+ return &EG(error_zval);
}
}
}
@@ -491,7 +490,7 @@ long_dim:
* and this is during runtime.
*/
zend_throw_error(NULL, "Cannot create unnamed attribute");
- return FAILURE;
+ return &EG(error_zval);
}
if (attribs && !node && sxe->iter.type == SXE_ITER_ELEMENT) {
node = xmlNewChild(mynode, mynode->ns, sxe->iter.name, NULL);
@@ -528,7 +527,7 @@ long_dim:
zval_ptr_dtor_str(&tmp_zv);
}
zend_error(E_WARNING, "It is not yet possible to assign complex types to %s", attribs ? "attributes" : "properties");
- return FAILURE;
+ return &EG(error_zval);
}
}
@@ -566,7 +565,7 @@ long_dim:
if (new_value) {
zval_ptr_dtor(value);
}
- return FAILURE;
+ return &EG(error_zval);
}
if (sxe->iter.type == SXE_ITER_NONE) {
@@ -574,7 +573,7 @@ long_dim:
++counter;
if (member && Z_LVAL_P(member) > 0) {
php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
- retval = FAILURE;
+ value = &EG(error_zval);
}
} else if (member) {
newnode = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
@@ -611,7 +610,7 @@ next_iter:
}
} else if (counter > 1) {
php_error_docref(NULL, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)");
- retval = FAILURE;
+ value = &EG(error_zval);
} else if (elements) {
if (!node) {
if (!member || Z_TYPE_P(member) == IS_LONG) {
@@ -622,14 +621,12 @@ next_iter:
} else if (!member || Z_TYPE_P(member) == IS_LONG) {
if (member && cnt < Z_LVAL_P(member)) {
php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only " ZEND_LONG_FMT " such elements exist", mynode->name, Z_LVAL_P(member), cnt);
- retval = FAILURE;
}
newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
}
} else if (attribs) {
if (Z_TYPE_P(member) == IS_LONG) {
php_error_docref(NULL, E_WARNING, "Cannot change attribute number " ZEND_LONG_FMT " when only %d attributes exist", Z_LVAL_P(member), nodendx);
- retval = FAILURE;
} else {
newnode = (xmlNodePtr)xmlNewProp(node, (xmlChar *)Z_STRVAL_P(member), value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
}
@@ -645,15 +642,17 @@ next_iter:
if (new_value) {
zval_ptr_dtor(value);
}
- return retval;
+ return value;
}
/* }}} */
/* {{{ sxe_property_write()
*/
-static void sxe_property_write(zval *object, zval *member, zval *value, void **cache_slot)
+static zval *sxe_property_write(zval *object, zval *member, zval *value, void **cache_slot)
{
- sxe_prop_dim_write(object, member, value, 1, 0, NULL);
+ zval *retval = sxe_prop_dim_write(object, member, value, 1, 0, NULL);
+
+ return retval == &EG(error_zval) ? &EG(uninitialized_zval) : retval;
}
/* }}} */
@@ -682,7 +681,7 @@ static zval *sxe_property_get_adr(zval *object, zval *member, int fetch_type, vo
if (node) {
return NULL;
}
- if (sxe_prop_dim_write(object, member, NULL, 1, 0, &node) != SUCCESS) {
+ if (sxe_prop_dim_write(object, member, NULL, 1, 0, &node) == &EG(error_zval)) {
return NULL;
}
type = SXE_ITER_NONE;
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index 7ee8ce416a..375d1556ad 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -1949,7 +1949,7 @@ zval *php_snmp_read_property(zval *object, zval *member, int type, void **cache_
/* {{{ php_snmp_write_property(zval *object, zval *member, zval *value[, const zend_literal *key])
Generic object property writer */
-void php_snmp_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+zval *php_snmp_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
zval tmp_member;
php_snmp_object *obj;
@@ -1973,12 +1973,14 @@ void php_snmp_write_property(zval *object, zval *member, zval *value, void **cac
}
*/
} else {
- zend_std_write_property(object, member, value, cache_slot);
+ value = zend_std_write_property(object, member, value, cache_slot);
}
if (member == &tmp_member) {
zval_ptr_dtor(member);
}
+
+ return value;
}
/* }}} */
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index c661dbd793..4888309d28 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -2800,7 +2800,7 @@ static void verify_soap_headers_array(HashTable *ht) /* {{{ */
}
/* }}} */
-/* {{{ proto mixed SoapClient::__call(string function_name, array arguments [, array options [, array input_headers [, array output_headers]]])
+/* {{{ proto mixed SoapClient::__call(string function_name, array arguments [, array options [, array input_headers [, array &output_headers]]])
Calls a SOAP function */
PHP_METHOD(SoapClient, __call)
{
@@ -2819,7 +2819,7 @@ PHP_METHOD(SoapClient, __call)
zend_bool free_soap_headers = 0;
zval *this_ptr;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|a!zz/",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|a!zz",
&function, &function_len, &args, &options, &headers, &output_headers) == FAILURE) {
return;
}
@@ -2891,14 +2891,18 @@ PHP_METHOD(SoapClient, __call)
} ZEND_HASH_FOREACH_END();
}
if (output_headers) {
- zval_ptr_dtor(output_headers);
- array_init(output_headers);
+ output_headers = zend_try_array_init(output_headers);
+ if (!output_headers) {
+ goto cleanup;
+ }
}
+
do_soap_call(execute_data, this_ptr, function, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers);
+
+cleanup:
if (arg_count > 0) {
efree(real_args);
}
-
if (soap_headers && free_soap_headers) {
zend_hash_destroy(soap_headers);
efree(soap_headers);
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 1f3a4cd4c7..f80075d3d5 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -1313,7 +1313,7 @@ PHP_FUNCTION(socket_getsockname)
char *addr_string;
socklen_t salen = sizeof(php_sockaddr_storage);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|z/", &arg1, &addr, &port) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|z", &arg1, &addr, &port) == FAILURE) {
return;
}
@@ -1337,12 +1337,10 @@ PHP_FUNCTION(socket_getsockname)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) sa;
inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
- zval_ptr_dtor(addr);
- ZVAL_STRING(addr, addr6);
+ ZEND_TRY_ASSIGN_STRING(addr, addr6);
if (port != NULL) {
- zval_ptr_dtor(port);
- ZVAL_LONG(port, htons(sin6->sin6_port));
+ ZEND_TRY_ASSIGN_LONG(port, htons(sin6->sin6_port));
}
RETURN_TRUE;
break;
@@ -1354,12 +1352,10 @@ PHP_FUNCTION(socket_getsockname)
addr_string = inet_ntoa(sin->sin_addr);
inet_ntoa_lock = 0;
- zval_ptr_dtor(addr);
- ZVAL_STRING(addr, addr_string);
+ ZEND_TRY_ASSIGN_STRING(addr, addr_string);
if (port != NULL) {
- zval_ptr_dtor(port);
- ZVAL_LONG(port, htons(sin->sin_port));
+ ZEND_TRY_ASSIGN_LONG(port, htons(sin->sin_port));
}
RETURN_TRUE;
break;
@@ -1367,8 +1363,7 @@ PHP_FUNCTION(socket_getsockname)
case AF_UNIX:
s_un = (struct sockaddr_un *) sa;
- zval_ptr_dtor(addr);
- ZVAL_STRING(addr, s_un->sun_path);
+ ZEND_TRY_ASSIGN_STRING(addr, s_un->sun_path);
RETURN_TRUE;
break;
@@ -1396,7 +1391,7 @@ PHP_FUNCTION(socket_getpeername)
char *addr_string;
socklen_t salen = sizeof(php_sockaddr_storage);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/|z/", &arg1, &arg2, &arg3) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|z", &arg1, &arg2, &arg3) == FAILURE) {
return;
}
@@ -1416,12 +1411,11 @@ PHP_FUNCTION(socket_getpeername)
case AF_INET6:
sin6 = (struct sockaddr_in6 *) sa;
inet_ntop(AF_INET6, &sin6->sin6_addr, addr6, INET6_ADDRSTRLEN);
- zval_ptr_dtor(arg2);
- ZVAL_STRING(arg2, addr6);
+
+ ZEND_TRY_ASSIGN_STRING(arg2, addr6);
if (arg3 != NULL) {
- zval_ptr_dtor(arg3);
- ZVAL_LONG(arg3, htons(sin6->sin6_port));
+ ZEND_TRY_ASSIGN_LONG(arg3, htons(sin6->sin6_port));
}
RETURN_TRUE;
@@ -1434,12 +1428,10 @@ PHP_FUNCTION(socket_getpeername)
addr_string = inet_ntoa(sin->sin_addr);
inet_ntoa_lock = 0;
- zval_ptr_dtor(arg2);
- ZVAL_STRING(arg2, addr_string);
+ ZEND_TRY_ASSIGN_STRING(arg2, addr_string);
if (arg3 != NULL) {
- zval_ptr_dtor(arg3);
- ZVAL_LONG(arg3, htons(sin->sin_port));
+ ZEND_TRY_ASSIGN_LONG(arg3, htons(sin->sin_port));
}
RETURN_TRUE;
@@ -1448,8 +1440,7 @@ PHP_FUNCTION(socket_getpeername)
case AF_UNIX:
s_un = (struct sockaddr_un *) sa;
- zval_ptr_dtor(arg2);
- ZVAL_STRING(arg2, s_un->sun_path);
+ ZEND_TRY_ASSIGN_STRING(arg2, s_un->sun_path);
RETURN_TRUE;
break;
@@ -1703,7 +1694,7 @@ PHP_FUNCTION(socket_recv)
int retval;
zend_long len, flags;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/ll", &php_sock_res, &buf, &len, &flags) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) {
return;
}
@@ -1720,16 +1711,11 @@ PHP_FUNCTION(socket_recv)
if ((retval = recv(php_sock->bsd_socket, ZSTR_VAL(recv_buf), len, flags)) < 1) {
zend_string_efree(recv_buf);
-
- zval_ptr_dtor(buf);
- ZVAL_NULL(buf);
+ ZEND_TRY_ASSIGN_NULL(buf);
} else {
ZSTR_LEN(recv_buf) = retval;
ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
-
- /* Rebuild buffer zval */
- zval_ptr_dtor(buf);
- ZVAL_NEW_STR(buf, recv_buf);
+ ZEND_TRY_ASSIGN_NEW_STR(buf, recv_buf);
}
if (retval == -1) {
@@ -1793,7 +1779,7 @@ PHP_FUNCTION(socket_recvfrom)
char *address;
zend_string *recv_buf;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/llz/|z/", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) {
return;
}
@@ -1824,11 +1810,8 @@ PHP_FUNCTION(socket_recvfrom)
ZSTR_LEN(recv_buf) = retval;
ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
- zval_ptr_dtor(arg2);
- zval_ptr_dtor(arg5);
-
- ZVAL_NEW_STR(arg2, recv_buf);
- ZVAL_STRING(arg5, s_un.sun_path);
+ ZEND_TRY_ASSIGN_NEW_STR(arg2, recv_buf);
+ ZEND_TRY_ASSIGN_STRING(arg5, s_un.sun_path);
break;
case AF_INET:
@@ -1851,15 +1834,11 @@ PHP_FUNCTION(socket_recvfrom)
ZSTR_LEN(recv_buf) = retval;
ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
- zval_ptr_dtor(arg2);
- zval_ptr_dtor(arg5);
- zval_ptr_dtor(arg6);
-
address = inet_ntoa(sin.sin_addr);
- ZVAL_NEW_STR(arg2, recv_buf);
- ZVAL_STRING(arg5, address ? address : "0.0.0.0");
- ZVAL_LONG(arg6, ntohs(sin.sin_port));
+ ZEND_TRY_ASSIGN_NEW_STR(arg2, recv_buf);
+ ZEND_TRY_ASSIGN_STRING(arg5, address ? address : "0.0.0.0");
+ ZEND_TRY_ASSIGN_LONG(arg6, ntohs(sin.sin_port));
break;
#if HAVE_IPV6
case AF_INET6:
@@ -1882,16 +1861,12 @@ PHP_FUNCTION(socket_recvfrom)
ZSTR_LEN(recv_buf) = retval;
ZSTR_VAL(recv_buf)[ZSTR_LEN(recv_buf)] = '\0';
- zval_ptr_dtor(arg2);
- zval_ptr_dtor(arg5);
- zval_ptr_dtor(arg6);
-
memset(addr6, 0, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &sin6.sin6_addr, addr6, INET6_ADDRSTRLEN);
- ZVAL_NEW_STR(arg2, recv_buf);
- ZVAL_STRING(arg5, addr6[0] ? addr6 : "::");
- ZVAL_LONG(arg6, ntohs(sin6.sin6_port));
+ ZEND_TRY_ASSIGN_NEW_STR(arg2, recv_buf);
+ ZEND_TRY_ASSIGN_STRING(arg5, addr6[0] ? addr6 : "::");
+ ZEND_TRY_ASSIGN_LONG(arg6, ntohs(sin6.sin6_port));
break;
#endif
default:
@@ -2253,7 +2228,7 @@ PHP_FUNCTION(socket_create_pair)
PHP_SOCKET fds_array[2];
zend_long domain, type, protocol;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lllz/", &domain, &type, &protocol, &fds_array_zval) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "lllz", &domain, &type, &protocol, &fds_array_zval) == FAILURE) {
return;
}
@@ -2282,8 +2257,12 @@ PHP_FUNCTION(socket_create_pair)
RETURN_FALSE;
}
- zval_ptr_dtor(fds_array_zval);
- array_init(fds_array_zval);
+ fds_array_zval = zend_try_array_init(fds_array_zval);
+ if (!fds_array_zval) {
+ efree(php_sock[0]);
+ efree(php_sock[1]);
+ return;
+ }
php_sock[0]->bsd_socket = fds_array[0];
php_sock[1]->bsd_socket = fds_array[1];
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 91dec7c09e..748263984a 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -878,16 +878,16 @@ static zval *spl_array_read_property(zval *object, zval *member, int type, void
return zend_std_read_property(object, member, type, cache_slot, rv);
} /* }}} */
-static void spl_array_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
+static zval *spl_array_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
{
spl_array_object *intern = Z_SPLARRAY_P(object);
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
&& !zend_std_has_property(object, member, ZEND_PROPERTY_EXISTS, NULL)) {
spl_array_write_dimension(object, member, value);
- return;
+ return value;
}
- zend_std_write_property(object, member, value, cache_slot);
+ return zend_std_write_property(object, member, value, cache_slot);
} /* }}} */
static zval *spl_array_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot) /* {{{ */
diff --git a/ext/spl/tests/iterator_035.phpt b/ext/spl/tests/iterator_035.phpt
index e6d68fbea6..0688635450 100644
--- a/ext/spl/tests/iterator_035.phpt
+++ b/ext/spl/tests/iterator_035.phpt
@@ -14,7 +14,7 @@ echo "Done\n";
--EXPECTF--
Notice: Indirect modification of overloaded element of ArrayIterator has no effect in %s on line %d
-Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d
+Fatal error: Uncaught Error: Cannot assign by reference to an array dimension of an object in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 33ea028602..8088c0da8a 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1786,9 +1786,11 @@ static zend_long php_extract_if_exists(zend_array *arr, zend_array *symbol_table
zend_throw_error(NULL, "Cannot re-assign $this");
return -1;
}
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_DEREF(orig_var, entry);
+ ZVAL_DEREF(entry);
+ ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
+ if (UNEXPECTED(EG(exception))) {
+ return -1;
+ }
count++;
}
} ZEND_HASH_FOREACH_END();
@@ -1869,9 +1871,11 @@ static zend_long php_extract_overwrite(zend_array *arr, zend_array *symbol_table
if (zend_string_equals_literal(var_name, "GLOBALS")) {
continue;
}
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY_DEREF(orig_var, entry);
+ ZVAL_DEREF(entry);
+ ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
+ if (UNEXPECTED(EG(exception))) {
+ return -1;
+ }
} else {
ZVAL_DEREF(entry);
Z_TRY_ADDREF_P(entry);
@@ -1971,9 +1975,11 @@ static zend_long php_extract_prefix_if_exists(zend_array *arr, zend_array *symbo
if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
orig_var = Z_INDIRECT_P(orig_var);
}
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY(orig_var, entry);
+ ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zend_string_release_ex(Z_STR(final_name), 0);
+ return -1;
+ }
} else {
Z_TRY_ADDREF_P(entry);
zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
@@ -2097,9 +2103,11 @@ static zend_long php_extract_prefix_same(zend_array *arr, zend_array *symbol_tab
if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
orig_var = Z_INDIRECT_P(orig_var);
}
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY(orig_var, entry);
+ ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zend_string_release_ex(Z_STR(final_name), 0);
+ return -1;
+ }
} else {
Z_TRY_ADDREF_P(entry);
zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
@@ -2202,9 +2210,11 @@ static zend_long php_extract_prefix_all(zend_array *arr, zend_array *symbol_tabl
if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
orig_var = Z_INDIRECT_P(orig_var);
}
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY(orig_var, entry);
+ ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zend_string_release_ex(Z_STR(final_name), 0);
+ return -1;
+ }
} else {
Z_TRY_ADDREF_P(entry);
zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
@@ -2309,9 +2319,11 @@ static zend_long php_extract_prefix_invalid(zend_array *arr, zend_array *symbol_
if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
orig_var = Z_INDIRECT_P(orig_var);
}
- ZVAL_DEREF(orig_var);
- zval_ptr_dtor(orig_var);
- ZVAL_COPY(orig_var, entry);
+ ZEND_TRY_ASSIGN_COPY_EX(orig_var, entry, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zend_string_release_ex(Z_STR(final_name), 0);
+ return -1;
+ }
} else {
Z_TRY_ADDREF_P(entry);
zend_hash_add_new(symbol_table, Z_STR(final_name), entry);
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 9026cacc79..38949a6080 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -4376,13 +4376,12 @@ PHP_FUNCTION(getopt)
Z_PARAM_STRING(options, options_len)
Z_PARAM_OPTIONAL
Z_PARAM_ARRAY(p_longopts)
- Z_PARAM_ZVAL_DEREF(zoptind)
+ Z_PARAM_ZVAL(zoptind)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
/* Init zoptind to 1 */
if (zoptind) {
- zval_ptr_dtor(zoptind);
- ZVAL_LONG(zoptind, 1);
+ ZEND_TRY_ASSIGN_LONG(zoptind, 1);
}
/* Get argv from the global symbol table. We calculate argc ourselves
@@ -4530,7 +4529,7 @@ PHP_FUNCTION(getopt)
/* Set zoptind to php_optind */
if (zoptind) {
- ZVAL_LONG(zoptind, php_optind);
+ ZEND_TRY_ASSIGN_LONG(zoptind, php_optind);
}
free_longopts(orig_opts);
diff --git a/ext/standard/dns.c b/ext/standard/dns.c
index 50f81153a5..15005dce0e 100644
--- a/ext/standard/dns.c
+++ b/ext/standard/dns.c
@@ -816,18 +816,22 @@ PHP_FUNCTION(dns_get_record)
Z_PARAM_STRING(hostname, hostname_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(type_param)
- Z_PARAM_ZVAL_DEREF_EX(authns, 1, 0)
- Z_PARAM_ZVAL_DEREF_EX(addtl, 1, 0)
+ Z_PARAM_ZVAL(authns)
+ Z_PARAM_ZVAL(addtl)
Z_PARAM_BOOL(raw)
ZEND_PARSE_PARAMETERS_END();
if (authns) {
- zval_ptr_dtor(authns);
- array_init(authns);
+ authns = zend_try_array_init(authns);
+ if (!authns) {
+ return;
+ }
}
if (addtl) {
- zval_ptr_dtor(addtl);
- array_init(addtl);
+ addtl = zend_try_array_init(addtl);
+ if (!addtl) {
+ return;
+ }
}
if (!raw) {
@@ -1049,17 +1053,21 @@ PHP_FUNCTION(dns_get_mx)
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STRING(hostname, hostname_len)
- Z_PARAM_ZVAL_DEREF(mx_list)
+ Z_PARAM_ZVAL(mx_list)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(weight_list)
+ Z_PARAM_ZVAL(weight_list)
ZEND_PARSE_PARAMETERS_END();
- zval_ptr_dtor(mx_list);
- array_init(mx_list);
+ mx_list = zend_try_array_init(mx_list);
+ if (!mx_list) {
+ return;
+ }
if (weight_list) {
- zval_ptr_dtor(weight_list);
- array_init(weight_list);
+ weight_list = zend_try_array_init(weight_list);
+ if (!weight_list) {
+ return;
+ }
}
#if defined(HAVE_DNS_SEARCH)
diff --git a/ext/standard/dns_win32.c b/ext/standard/dns_win32.c
index aa11a01f47..393b41d0e8 100644
--- a/ext/standard/dns_win32.c
+++ b/ext/standard/dns_win32.c
@@ -50,7 +50,7 @@ PHP_FUNCTION(dns_get_mx) /* {{{ */
DNS_STATUS status; /* Return value of DnsQuery_A() function */
PDNS_RECORD pResult, pRec; /* Pointer to DNS_RECORD structure */
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/|z/", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) {
return;
}
@@ -60,12 +60,16 @@ PHP_FUNCTION(dns_get_mx) /* {{{ */
RETURN_FALSE;
}
- zval_ptr_dtor(mx_list);
- array_init(mx_list);
+ mx_list = zend_try_array_init(mx_list);
+ if (!mx_list) {
+ goto cleanup;
+ }
if (weight_list) {
- zval_ptr_dtor(weight_list);
- array_init(weight_list);
+ weight_list = zend_try_array_init(weight_list);
+ if (!weight_list) {
+ goto cleanup;
+ }
}
for (pRec = pResult; pRec; pRec = pRec->pNext) {
@@ -81,6 +85,7 @@ PHP_FUNCTION(dns_get_mx) /* {{{ */
}
}
+cleanup:
/* Free memory allocated for DNS records. */
DnsRecordListFree(pResult, DnsFreeRecordListDeep);
@@ -352,18 +357,22 @@ PHP_FUNCTION(dns_get_record)
int type, type_to_fetch, first_query = 1, store_results = 1;
zend_bool raw = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz/!z/!b",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz!z!b",
&hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
return;
}
if (authns) {
- zval_ptr_dtor(authns);
- array_init(authns);
+ authns = zend_try_array_init(authns);
+ if (!authns) {
+ return;
+ }
}
if (addtl) {
- zval_ptr_dtor(addtl);
- array_init(addtl);
+ addtl = zend_try_array_init(addtl);
+ if (!addtl) {
+ return;
+ }
}
if (!raw) {
diff --git a/ext/standard/exec.c b/ext/standard/exec.c
index 5b885c554d..bfad4173a7 100644
--- a/ext/standard/exec.c
+++ b/ext/standard/exec.c
@@ -216,9 +216,9 @@ static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
Z_PARAM_STRING(cmd, cmd_len)
Z_PARAM_OPTIONAL
if (!mode) {
- Z_PARAM_ZVAL_DEREF(ret_array)
+ Z_PARAM_ZVAL(ret_array)
}
- Z_PARAM_ZVAL_DEREF(ret_code)
+ Z_PARAM_ZVAL(ret_code)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
if (!cmd_len) {
@@ -233,18 +233,20 @@ static void php_exec_ex(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
if (!ret_array) {
ret = php_exec(mode, cmd, NULL, return_value);
} else {
- if (Z_TYPE_P(ret_array) != IS_ARRAY) {
- zval_ptr_dtor(ret_array);
- array_init(ret_array);
- } else if (Z_REFCOUNT_P(ret_array) > 1) {
- zval_ptr_dtor(ret_array);
- ZVAL_ARR(ret_array, zend_array_dup(Z_ARR_P(ret_array)));
+ if (Z_TYPE_P(Z_REFVAL_P(ret_array)) == IS_ARRAY) {
+ ZVAL_DEREF(ret_array);
+ SEPARATE_ARRAY(ret_array);
+ } else {
+ ret_array = zend_try_array_init(ret_array);
+ if (!ret_array) {
+ return;
+ }
}
+
ret = php_exec(2, cmd, ret_array, return_value);
}
if (ret_code) {
- zval_ptr_dtor(ret_code);
- ZVAL_LONG(ret_code, ret);
+ ZEND_TRY_ASSIGN_LONG(ret_code, ret);
}
}
/* }}} */
diff --git a/ext/standard/file.c b/ext/standard/file.c
index c962ba4824..93b58e9a94 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -343,7 +343,7 @@ PHP_FUNCTION(flock)
Z_PARAM_RESOURCE(res)
Z_PARAM_LONG(operation)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(wouldblock)
+ Z_PARAM_ZVAL(wouldblock)
ZEND_PARSE_PARAMETERS_END();
PHP_STREAM_TO_ZVAL(stream, res);
@@ -355,15 +355,14 @@ PHP_FUNCTION(flock)
}
if (wouldblock) {
- zval_ptr_dtor(wouldblock);
- ZVAL_LONG(wouldblock, 0);
+ ZEND_TRY_ASSIGN_LONG(wouldblock, 0);
}
/* flock_values contains all possible actions if (operation & 4) we won't block on the lock */
act = flock_values[act - 1] | (operation & PHP_LOCK_NB ? LOCK_NB : 0);
if (php_stream_lock(stream, act)) {
if (operation && errno == EWOULDBLOCK && wouldblock) {
- ZVAL_LONG(wouldblock, 1);
+ ZEND_TRY_ASSIGN_LONG(wouldblock, 1);
}
RETURN_FALSE;
}
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c
index 6fc7143cd6..32e651d1e4 100644
--- a/ext/standard/fsock.c
+++ b/ext/standard/fsock.c
@@ -53,8 +53,8 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
Z_PARAM_STRING(host, host_len)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(port)
- Z_PARAM_ZVAL_DEREF(zerrno)
- Z_PARAM_ZVAL_DEREF(zerrstr)
+ Z_PARAM_ZVAL(zerrno)
+ Z_PARAM_ZVAL(zerrstr)
Z_PARAM_DOUBLE(timeout)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
@@ -79,15 +79,6 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
#endif
tv.tv_usec = conv % 1000000;
- if (zerrno) {
- zval_ptr_dtor(zerrno);
- ZVAL_LONG(zerrno, 0);
- }
- if (zerrstr) {
- zval_ptr_dtor(zerrstr);
- ZVAL_EMPTY_STRING(zerrstr);
- }
-
stream = php_stream_xport_create(hostname, hostname_len, REPORT_ERRORS,
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, hashkey, &tv, NULL, &errstr, &err);
@@ -102,22 +93,27 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent)
efree(hashkey);
}
- if (stream == NULL) {
+ if (stream == NULL) {
if (zerrno) {
- zval_ptr_dtor(zerrno);
- ZVAL_LONG(zerrno, err);
+ ZEND_TRY_ASSIGN_LONG(zerrno, err);
}
- if (zerrstr && errstr) {
- /* no need to dup; we need to efree buf anyway */
- zval_ptr_dtor(zerrstr);
- ZVAL_STR(zerrstr, errstr);
- } else if (!zerrstr && errstr) {
- zend_string_release_ex(errstr, 0);
+ if (errstr) {
+ if (zerrstr) {
+ ZEND_TRY_ASSIGN_STR(zerrstr, errstr);
+ }
+ zend_string_release(errstr);
}
RETURN_FALSE;
}
+ if (zerrno) {
+ ZEND_TRY_ASSIGN_LONG(zerrno, 0);
+ }
+ if (zerrstr) {
+ ZEND_TRY_ASSIGN_EMPTY_STRING(zerrstr);
+ }
+
if (errstr) {
zend_string_release_ex(errstr, 0);
}
diff --git a/ext/standard/head.c b/ext/standard/head.c
index 302599f02b..be2b2668f0 100644
--- a/ext/standard/head.c
+++ b/ext/standard/head.c
@@ -358,8 +358,8 @@ PHP_FUNCTION(headers_sent)
ZEND_PARSE_PARAMETERS_START(0, 2)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(arg1)
- Z_PARAM_ZVAL_DEREF(arg2)
+ Z_PARAM_ZVAL(arg1)
+ Z_PARAM_ZVAL(arg2)
ZEND_PARSE_PARAMETERS_END();
if (SG(headers_sent)) {
@@ -369,14 +369,12 @@ PHP_FUNCTION(headers_sent)
switch(ZEND_NUM_ARGS()) {
case 2:
- zval_ptr_dtor(arg2);
- ZVAL_LONG(arg2, line);
+ ZEND_TRY_ASSIGN_LONG(arg2, line);
case 1:
- zval_ptr_dtor(arg1);
if (file) {
- ZVAL_STRING(arg1, file);
+ ZEND_TRY_ASSIGN_STRING(arg1, file);
} else {
- ZVAL_EMPTY_STRING(arg1);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(arg1);
}
break;
}
diff --git a/ext/standard/image.c b/ext/standard/image.c
index d32d1499f3..cf9ba12be8 100644
--- a/ext/standard/image.c
+++ b/ext/standard/image.c
@@ -1493,12 +1493,14 @@ static void php_getimagesize_from_any(INTERNAL_FUNCTION_PARAMETERS, int mode) {
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STRING(input, input_len)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(info)
+ Z_PARAM_ZVAL(info)
ZEND_PARSE_PARAMETERS_END();
if (argc == 2) {
- zval_ptr_dtor(info);
- array_init(info);
+ info = zend_try_array_init(info);
+ if (!info) {
+ return;
+ }
}
if (mode == FROM_PATH) {
diff --git a/ext/standard/incomplete_class.c b/ext/standard/incomplete_class.c
index 943dafaa43..87a17ab7f6 100644
--- a/ext/standard/incomplete_class.c
+++ b/ext/standard/incomplete_class.c
@@ -60,9 +60,10 @@ static zval *incomplete_class_get_property(zval *object, zval *member, int type,
}
/* }}} */
-static void incomplete_class_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
+static zval *incomplete_class_write_property(zval *object, zval *member, zval *value, void **cache_slot) /* {{{ */
{
incomplete_class_message(object, E_NOTICE);
+ return value;
}
/* }}} */
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index 612cdf0f88..8347ea7864 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -447,7 +447,7 @@ PHP_FUNCTION(proc_open)
ZEND_PARSE_PARAMETERS_START(3, 6)
Z_PARAM_STRING(command, command_len)
Z_PARAM_ARRAY(descriptorspec)
- Z_PARAM_ZVAL_DEREF(pipes)
+ Z_PARAM_ZVAL(pipes)
Z_PARAM_OPTIONAL
Z_PARAM_STRING_EX(cwd, cwd_len, 1, 0)
Z_PARAM_ARRAY_EX(environment, 1, 0)
@@ -862,6 +862,11 @@ PHP_FUNCTION(proc_open)
#endif
/* we forked/spawned and this is the parent */
+ pipes = zend_try_array_init(pipes);
+ if (!pipes) {
+ goto exit_fail;
+ }
+
proc = (struct php_process_handle*)pemalloc(sizeof(struct php_process_handle), is_persistent);
proc->is_persistent = is_persistent;
proc->command = command;
@@ -873,9 +878,6 @@ PHP_FUNCTION(proc_open)
#endif
proc->env = env;
- zval_ptr_dtor(pipes);
- array_init(pipes);
-
#if PHP_CAN_DO_PTS
if (dev_ptmx >= 0) {
close(dev_ptmx);
diff --git a/ext/standard/scanf.c b/ext/standard/scanf.c
index 37cce100ce..6c7544004b 100644
--- a/ext/standard/scanf.c
+++ b/ext/standard/scanf.c
@@ -739,9 +739,8 @@ literal:
if (numVars && objIndex >= argCount) {
break;
} else if (numVars) {
- current = Z_REFVAL(args[objIndex++]);
- zval_ptr_dtor(current);
- ZVAL_LONG(current, (zend_long)(string - baseString) );
+ current = args + objIndex++;
+ ZEND_TRY_ASSIGN_LONG(current, (zend_long) (string - baseString));
} else {
add_index_long(return_value, objIndex++, string - baseString);
}
@@ -858,9 +857,8 @@ literal:
if (numVars && objIndex >= argCount) {
break;
} else if (numVars) {
- current = Z_REFVAL(args[objIndex++]);
- zval_ptr_dtor(current);
- ZVAL_STRINGL(current, string, end-string);
+ current = args + objIndex++;
+ ZEND_TRY_ASSIGN_STRINGL(current, string, end - string);
} else {
add_index_stringl(return_value, objIndex++, string, end-string);
}
@@ -899,9 +897,8 @@ literal:
if (numVars && objIndex >= argCount) {
break;
} else if (numVars) {
- current = Z_REFVAL(args[objIndex++]);
- zval_ptr_dtor(current);
- ZVAL_STRINGL(current, string, end-string);
+ current = args + objIndex++;
+ ZEND_TRY_ASSIGN_STRINGL(current, string, end - string);
} else {
add_index_stringl(return_value, objIndex++, string, end-string);
}
@@ -1052,10 +1049,9 @@ addToInt:
if (numVars && objIndex >= argCount) {
break;
} else if (numVars) {
- /* change passed value type to string */
- current = Z_REFVAL(args[objIndex++]);
- zval_ptr_dtor(current);
- ZVAL_STRING(current, buf);
+ /* change passed value type to string */
+ current = args + objIndex++;
+ ZEND_TRY_ASSIGN_STRING(current, buf);
} else {
add_index_string(return_value, objIndex++, buf);
}
@@ -1063,9 +1059,8 @@ addToInt:
if (numVars && objIndex >= argCount) {
break;
} else if (numVars) {
- current = Z_REFVAL(args[objIndex++]);
- zval_ptr_dtor(current);
- ZVAL_LONG(current, value);
+ current = args + objIndex++;
+ ZEND_TRY_ASSIGN_LONG(current, value);
} else {
add_index_long(return_value, objIndex++, value);
}
@@ -1168,9 +1163,8 @@ addToFloat:
if (numVars && objIndex >= argCount) {
break;
} else if (numVars) {
- current = Z_REFVAL(args[objIndex++]);
- zval_ptr_dtor(current);
- ZVAL_DOUBLE(current, dvalue);
+ current = args + objIndex++;
+ ZEND_TRY_ASSIGN_DOUBLE(current, dvalue);
} else {
add_index_double(return_value, objIndex++, dvalue );
}
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index 442091ad46..8f67b8b3fc 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -107,8 +107,8 @@ PHP_FUNCTION(stream_socket_client)
ZEND_PARSE_PARAMETERS_START(1, 6)
Z_PARAM_STR(host)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(zerrno)
- Z_PARAM_ZVAL_DEREF(zerrstr)
+ Z_PARAM_ZVAL(zerrno)
+ Z_PARAM_ZVAL(zerrstr)
Z_PARAM_DOUBLE(timeout)
Z_PARAM_LONG(flags)
Z_PARAM_RESOURCE(zcontext)
@@ -129,13 +129,11 @@ PHP_FUNCTION(stream_socket_client)
tv.tv_sec = conv / 1000000;
tv.tv_usec = conv % 1000000;
#endif
- if (zerrno) {
- zval_ptr_dtor(zerrno);
- ZVAL_LONG(zerrno, 0);
+ if (zerrno) {
+ ZEND_TRY_ASSIGN_LONG(zerrno, 0);
}
if (zerrstr) {
- zval_ptr_dtor(zerrstr);
- ZVAL_EMPTY_STRING(zerrstr);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(zerrstr);
}
stream = php_stream_xport_create(ZSTR_VAL(host), ZSTR_LEN(host), REPORT_ERRORS,
@@ -156,14 +154,12 @@ PHP_FUNCTION(stream_socket_client)
efree(hashkey);
}
- if (stream == NULL) {
+ if (stream == NULL) {
if (zerrno) {
- zval_ptr_dtor(zerrno);
- ZVAL_LONG(zerrno, err);
+ ZEND_TRY_ASSIGN_LONG(zerrno, err);
}
if (zerrstr && errstr) {
- zval_ptr_dtor(zerrstr);
- ZVAL_STR(zerrstr, errstr);
+ ZEND_TRY_ASSIGN_STR(zerrstr, errstr);
} else if (errstr) {
zend_string_release_ex(errstr, 0);
}
@@ -197,8 +193,8 @@ PHP_FUNCTION(stream_socket_server)
ZEND_PARSE_PARAMETERS_START(1, 5)
Z_PARAM_STRING(host, host_len)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(zerrno)
- Z_PARAM_ZVAL_DEREF(zerrstr)
+ Z_PARAM_ZVAL(zerrno)
+ Z_PARAM_ZVAL(zerrstr)
Z_PARAM_LONG(flags)
Z_PARAM_RESOURCE(zcontext)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
@@ -209,13 +205,11 @@ PHP_FUNCTION(stream_socket_server)
GC_ADDREF(context->res);
}
- if (zerrno) {
- zval_ptr_dtor(zerrno);
- ZVAL_LONG(zerrno, 0);
+ if (zerrno) {
+ ZEND_TRY_ASSIGN_LONG(zerrno, 0);
}
if (zerrstr) {
- zval_ptr_dtor(zerrstr);
- ZVAL_EMPTY_STRING(zerrstr);
+ ZEND_TRY_ASSIGN_EMPTY_STRING(zerrstr);
}
stream = php_stream_xport_create(host, host_len, REPORT_ERRORS,
@@ -226,14 +220,12 @@ PHP_FUNCTION(stream_socket_server)
php_error_docref(NULL, E_WARNING, "unable to connect to %s (%s)", host, errstr == NULL ? "Unknown error" : ZSTR_VAL(errstr));
}
- if (stream == NULL) {
+ if (stream == NULL) {
if (zerrno) {
- zval_ptr_dtor(zerrno);
- ZVAL_LONG(zerrno, err);
+ ZEND_TRY_ASSIGN_LONG(zerrno, err);
}
if (zerrstr && errstr) {
- zval_ptr_dtor(zerrstr);
- ZVAL_STR(zerrstr, errstr);
+ ZEND_TRY_ASSIGN_STR(zerrstr, errstr);
} else if (errstr) {
zend_string_release_ex(errstr, 0);
}
@@ -265,7 +257,7 @@ PHP_FUNCTION(stream_socket_accept)
Z_PARAM_RESOURCE(zstream)
Z_PARAM_OPTIONAL
Z_PARAM_DOUBLE(timeout)
- Z_PARAM_ZVAL_DEREF(zpeername)
+ Z_PARAM_ZVAL(zpeername)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
php_stream_from_zval(stream, zstream);
@@ -279,10 +271,6 @@ PHP_FUNCTION(stream_socket_accept)
tv.tv_sec = conv / 1000000;
tv.tv_usec = conv % 1000000;
#endif
- if (zpeername) {
- zval_ptr_dtor(zpeername);
- ZVAL_NULL(zpeername);
- }
if (0 == php_stream_xport_accept(stream, &clistream,
zpeername ? &peername : NULL,
@@ -291,7 +279,7 @@ PHP_FUNCTION(stream_socket_accept)
) && clistream) {
if (peername) {
- ZVAL_STR(zpeername, peername);
+ ZEND_TRY_ASSIGN_STR(zpeername, peername);
}
php_stream_to_zval(clistream, return_value);
} else {
@@ -387,14 +375,13 @@ PHP_FUNCTION(stream_socket_recvfrom)
Z_PARAM_LONG(to_read)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(flags)
- Z_PARAM_ZVAL_DEREF(zremote)
+ Z_PARAM_ZVAL(zremote)
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
php_stream_from_zval(stream, zstream);
if (zremote) {
- zval_ptr_dtor(zremote);
- ZVAL_NULL(zremote);
+ ZEND_TRY_ASSIGN_NULL(zremote);
}
if (to_read <= 0) {
@@ -410,7 +397,7 @@ PHP_FUNCTION(stream_socket_recvfrom)
if (recvd >= 0) {
if (zremote && remote_addr) {
- ZVAL_STR(zremote, remote_addr);
+ ZEND_TRY_ASSIGN_STR(zremote, remote_addr);
}
ZSTR_VAL(read_buf)[recvd] = '\0';
ZSTR_LEN(read_buf) = recvd;
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 26144eb166..3839512ecc 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -3655,16 +3655,12 @@ PHP_FUNCTION(similar_text)
Z_PARAM_STR(t1)
Z_PARAM_STR(t2)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(percent)
+ Z_PARAM_ZVAL(percent)
ZEND_PARSE_PARAMETERS_END();
- if (ac > 2) {
- convert_to_double_ex(percent);
- }
-
if (ZSTR_LEN(t1) + ZSTR_LEN(t2) == 0) {
if (ac > 2) {
- Z_DVAL_P(percent) = 0;
+ ZEND_TRY_ASSIGN_DOUBLE(percent, 0);
}
RETURN_LONG(0);
@@ -3673,7 +3669,7 @@ PHP_FUNCTION(similar_text)
sim = php_similar_char(ZSTR_VAL(t1), ZSTR_LEN(t1), ZSTR_VAL(t2), ZSTR_LEN(t2));
if (ac > 2) {
- Z_DVAL_P(percent) = sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2));
+ ZEND_TRY_ASSIGN_DOUBLE(percent, sim * 200.0 / (ZSTR_LEN(t1) + ZSTR_LEN(t2)));
}
RETURN_LONG(sim);
@@ -4442,7 +4438,7 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
Z_PARAM_ZVAL(replace)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(zcount)
+ Z_PARAM_ZVAL(zcount)
ZEND_PARSE_PARAMETERS_END();
/* Make sure we're dealing with strings and do the replacement. */
@@ -4479,8 +4475,7 @@ static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensit
count = php_str_replace_in_subject(search, replace, subject, return_value, case_sensitivity);
}
if (argc > 3) {
- zval_ptr_dtor(zcount);
- ZVAL_LONG(zcount, count);
+ ZEND_TRY_ASSIGN_LONG(zcount, count);
}
}
/* }}} */
@@ -4906,7 +4901,7 @@ PHP_FUNCTION(parse_str)
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STRING(arg, arglen)
Z_PARAM_OPTIONAL
- Z_PARAM_ZVAL_DEREF(arrayArg)
+ Z_PARAM_ZVAL(arrayArg)
ZEND_PARSE_PARAMETERS_END();
res = estrndup(arg, arglen);
@@ -4928,9 +4923,11 @@ PHP_FUNCTION(parse_str)
zend_throw_error(NULL, "Cannot re-assign $this");
}
} else {
- /* Clear out the array that was passed in. */
- zval_ptr_dtor(arrayArg);
- array_init(arrayArg);
+ arrayArg = zend_try_array_init(arrayArg);
+ if (!arrayArg) {
+ return;
+ }
+
sapi_module.treat_data(PARSE_STRING, res, arrayArg);
}
}
diff --git a/ext/standard/tests/array/extract_typed_ref.phpt b/ext/standard/tests/array/extract_typed_ref.phpt
new file mode 100644
index 0000000000..8b697d5ccb
--- /dev/null
+++ b/ext/standard/tests/array/extract_typed_ref.phpt
@@ -0,0 +1,23 @@
+--TEST--
+extract() into typed references must respect their type
+--FILE--
+<?php
+
+class Test {
+ public int $i = 0;
+ public string $s = "";
+}
+
+$test = new Test;
+$i =& $test->i;
+$s =& $test->s;
+try {
+ extract(['i' => 'foo', 's' => 42]);
+} catch (TypeError $e) { echo $e->getMessage(), "\n"; }
+var_dump($test->i, $test->s);
+
+?>
+--EXPECT--
+Cannot assign string to reference held by property Test::$i of type int
+int(0)
+string(0) ""
diff --git a/ext/standard/tests/general_functions/settype_typed_property.phpt b/ext/standard/tests/general_functions/settype_typed_property.phpt
new file mode 100644
index 0000000000..a206a4ba41
--- /dev/null
+++ b/ext/standard/tests/general_functions/settype_typed_property.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Using settype() on a typed property
+--FILE--
+<?php
+
+class Test {
+ public int $x;
+}
+
+$test = new Test;
+$test->x = 42;
+settype($test->x, 'string');
+// Same as $test->x = (string) $test->x.
+// Leaves value unchanged due to coercion
+var_dump($test->x);
+
+try {
+ settype($test->x, 'array');
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($test->x);
+
+?>
+--EXPECT--
+int(42)
+Cannot assign array to reference held by property Test::$x of type int
+int(42)
diff --git a/ext/standard/tests/serialize/typed_property_refs.phpt b/ext/standard/tests/serialize/typed_property_refs.phpt
new file mode 100644
index 0000000000..9475e8a783
--- /dev/null
+++ b/ext/standard/tests/serialize/typed_property_refs.phpt
@@ -0,0 +1,73 @@
+--TEST--
+unserialize with references to typed properties shall skip the references or fail
+--FILE--
+<?php
+
+class A {
+ public int $a;
+ public $b;
+}
+
+class B {
+ public $a;
+ public int $b;
+}
+
+class C {
+ public int $a;
+ public string $b;
+}
+
+class D {
+ public int $a;
+ public float $b;
+}
+
+var_dump(unserialize('O:1:"A":2:{s:1:"a";i:1;s:1:"b";R:2;}'));
+var_dump(unserialize('O:1:"B":2:{s:1:"a";i:1;s:1:"b";R:2;}'));
+
+try {
+ var_dump(unserialize('O:1:"A":2:{s:1:"a";N;s:1:"b";R:2;}'));
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(unserialize('O:1:"B":2:{s:1:"a";N;s:1:"b";R:2;}'));
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(unserialize('O:1:"C":2:{s:1:"a";i:1;s:1:"b";R:2;}'));
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(unserialize('O:1:"C":2:{s:1:"b";s:1:"x";s:1:"a";R:2;}'));
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+try {
+ var_dump(unserialize('O:1:"D":2:{s:1:"a";i:1;s:1:"b";R:2;}'));
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+object(A)#1 (2) {
+ ["a"]=>
+ &int(1)
+ ["b"]=>
+ &int(1)
+}
+object(B)#1 (2) {
+ ["a"]=>
+ &int(1)
+ ["b"]=>
+ &int(1)
+}
+Typed property A::$a must be int, null used
+Typed property B::$b must be int, null used
+Typed property C::$b must be string, int used
+Typed property C::$a must be int, string used
+Reference with value of type int held by property D::$a of type int is not compatible with property D::$b of type float
diff --git a/ext/standard/type.c b/ext/standard/type.c
index 1a26e0eaa3..bc1233e35d 100644
--- a/ext/standard/type.c
+++ b/ext/standard/type.c
@@ -45,40 +45,46 @@ PHP_FUNCTION(settype)
{
zval *var;
char *type;
- size_t type_len = 0;
+ size_t type_len;
+ zval tmp;
ZEND_PARSE_PARAMETERS_START(2, 2)
- Z_PARAM_ZVAL_DEREF(var)
+ Z_PARAM_ZVAL(var)
Z_PARAM_STRING(type, type_len)
ZEND_PARSE_PARAMETERS_END();
+ ZVAL_COPY(&tmp, var);
if (!strcasecmp(type, "integer")) {
- convert_to_long(var);
+ convert_to_long(&tmp);
} else if (!strcasecmp(type, "int")) {
- convert_to_long(var);
+ convert_to_long(&tmp);
} else if (!strcasecmp(type, "float")) {
- convert_to_double(var);
+ convert_to_double(&tmp);
} else if (!strcasecmp(type, "double")) { /* deprecated */
- convert_to_double(var);
+ convert_to_double(&tmp);
} else if (!strcasecmp(type, "string")) {
- convert_to_string(var);
+ convert_to_string(&tmp);
} else if (!strcasecmp(type, "array")) {
- convert_to_array(var);
+ convert_to_array(&tmp);
} else if (!strcasecmp(type, "object")) {
- convert_to_object(var);
+ convert_to_object(&tmp);
} else if (!strcasecmp(type, "bool")) {
- convert_to_boolean(var);
+ convert_to_boolean(&tmp);
} else if (!strcasecmp(type, "boolean")) {
- convert_to_boolean(var);
+ convert_to_boolean(&tmp);
} else if (!strcasecmp(type, "null")) {
- convert_to_null(var);
+ convert_to_null(&tmp);
} else if (!strcasecmp(type, "resource")) {
+ zval_ptr_dtor(&tmp);
php_error_docref(NULL, E_WARNING, "Cannot convert to resource type");
RETURN_FALSE;
} else {
+ zval_ptr_dtor(&tmp);
php_error_docref(NULL, E_WARNING, "Invalid type");
RETURN_FALSE;
}
+
+ zend_try_assign(var, &tmp);
RETVAL_TRUE;
}
/* }}} */
@@ -357,7 +363,7 @@ PHP_FUNCTION(is_callable)
Z_PARAM_ZVAL(var)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(syntax_only)
- Z_PARAM_ZVAL_DEREF(callable_name)
+ Z_PARAM_ZVAL(callable_name)
ZEND_PARSE_PARAMETERS_END();
if (syntax_only) {
@@ -365,8 +371,7 @@ PHP_FUNCTION(is_callable)
}
if (ZEND_NUM_ARGS() > 2) {
retval = zend_is_callable_ex(var, NULL, check_flags, &name, NULL, &error);
- zval_ptr_dtor(callable_name);
- ZVAL_STR(callable_name, name);
+ ZEND_TRY_ASSIGN_STR(callable_name, name);
} else {
retval = zend_is_callable_ex(var, NULL, check_flags, NULL, NULL, &error);
}
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 108bafca8b..27ec44f991 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -51,7 +51,7 @@ static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key,
}
/* }}} */
-static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
+static void php_object_property_dump(zend_property_info *prop_info, zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
{
const char *prop_name, *class_name;
@@ -74,7 +74,18 @@ static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *ke
}
ZEND_PUTS("]=>\n");
}
- php_var_dump(zv, level + 2);
+
+ if (Z_TYPE_P(zv) == IS_UNDEF) {
+ ZEND_ASSERT(prop_info->type);
+ php_printf("%*cuninitialized(%s%s)\n",
+ level + 1, ' ',
+ ZEND_TYPE_ALLOW_NULL(prop_info->type) ? "?" : "",
+ ZEND_TYPE_IS_CLASS(prop_info->type) ?
+ ZSTR_VAL(ZEND_TYPE_IS_CE(prop_info->type) ? ZEND_TYPE_CE(prop_info->type)->name : ZEND_TYPE_NAME(prop_info->type)) :
+ zend_get_type_by_const(ZEND_TYPE_CODE(prop_info->type)));
+ } else {
+ php_var_dump(zv, level + 2);
+ }
}
/* }}} */
@@ -154,8 +165,19 @@ again:
zend_string *key;
zval *val;
- ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
- php_object_property_dump(val, num, key, level);
+ ZEND_HASH_FOREACH_KEY_VAL(myht, num, key, val) {
+ zend_property_info *prop_info = NULL;
+
+ if (Z_TYPE_P(val) == IS_INDIRECT) {
+ val = Z_INDIRECT_P(val);
+ if (key) {
+ prop_info = zend_get_typed_property_info_for_slot(Z_OBJ_P(struc), val);
+ }
+ }
+
+ if (!Z_ISUNDEF_P(val) || prop_info) {
+ php_object_property_dump(prop_info, val, num, key, level);
+ }
} ZEND_HASH_FOREACH_END();
zend_release_properties(myht);
}
@@ -216,7 +238,7 @@ static void zval_array_element_dump(zval *zv, zend_ulong index, zend_string *key
}
/* }}} */
-static void zval_object_property_dump(zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
+static void zval_object_property_dump(zend_property_info *prop_info, zval *zv, zend_ulong index, zend_string *key, int level) /* {{{ */
{
const char *prop_name, *class_name;
@@ -237,7 +259,17 @@ static void zval_object_property_dump(zval *zv, zend_ulong index, zend_string *k
}
ZEND_PUTS("]=>\n");
}
- php_debug_zval_dump(zv, level + 2);
+ if (prop_info && Z_TYPE_P(zv) == IS_UNDEF) {
+ ZEND_ASSERT(prop_info->type);
+ php_printf("%*cuninitialized(%s%s)\n",
+ level + 1, ' ',
+ ZEND_TYPE_ALLOW_NULL(prop_info->type) ? "?" : "",
+ ZEND_TYPE_IS_CLASS(prop_info->type) ?
+ ZSTR_VAL(ZEND_TYPE_IS_CE(prop_info->type) ? ZEND_TYPE_CE(prop_info->type)->name : ZEND_TYPE_NAME(prop_info->type)) :
+ zend_get_type_by_const(ZEND_TYPE_CODE(prop_info->type)));
+ } else {
+ php_debug_zval_dump(zv, level + 2);
+ }
}
/* }}} */
@@ -313,8 +345,19 @@ again:
php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0, Z_REFCOUNT_P(struc));
zend_string_release_ex(class_name, 0);
if (myht) {
- ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
- zval_object_property_dump(val, index, key, level);
+ ZEND_HASH_FOREACH_KEY_VAL(myht, index, key, val) {
+ zend_property_info *prop_info = NULL;
+
+ if (Z_TYPE_P(val) == IS_INDIRECT) {
+ val = Z_INDIRECT_P(val);
+ if (key) {
+ prop_info = zend_get_typed_property_info_for_slot(Z_OBJ_P(struc), val);
+ }
+ }
+
+ if (!Z_ISUNDEF_P(val) || prop_info) {
+ zval_object_property_dump(prop_info, val, index, key, level);
+ }
} ZEND_HASH_FOREACH_END();
GC_UNPROTECT_RECURSION(myht);
zend_release_properties(myht);
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index d07d657719..8dad71450e 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -46,6 +46,7 @@ struct php_unserialize_data {
var_dtor_entries *first_dtor;
var_dtor_entries *last_dtor;
HashTable *allowed_classes;
+ HashTable *ref_props;
var_entries entries;
};
@@ -57,6 +58,7 @@ PHPAPI php_unserialize_data_t php_var_unserialize_init() {
d->last = &d->entries;
d->first_dtor = d->last_dtor = NULL;
d->allowed_classes = NULL;
+ d->ref_props = NULL;
d->entries.used_slots = 0;
d->entries.next = NULL;
if (!BG(serialize_lock)) {
@@ -239,6 +241,11 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx)
}
zval_ptr_dtor_nogc(&wakeup_name);
+
+ if ((*var_hashx)->ref_props) {
+ zend_hash_destroy((*var_hashx)->ref_props);
+ FREE_HASHTABLE((*var_hashx)->ref_props);
+ }
}
/* }}} */
@@ -395,11 +402,12 @@ static inline size_t parse_uiv(const unsigned char *p)
static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key);
-static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
+static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, zend_object *obj)
{
while (elements-- > 0) {
zval key, *data, d, *old_data;
zend_ulong idx;
+ zend_property_info *info = NULL;
ZVAL_UNDEF(&key);
@@ -411,7 +419,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab
data = NULL;
ZVAL_UNDEF(&d);
- if (!objprops) {
+ if (!obj) {
if (Z_TYPE(key) == IS_LONG) {
idx = Z_LVAL(key);
numeric_key:
@@ -440,8 +448,7 @@ numeric_key:
} else {
if (EXPECTED(Z_TYPE(key) == IS_STRING)) {
string_key:
- if (Z_TYPE_P(rval) == IS_OBJECT
- && zend_hash_num_elements(&Z_OBJCE_P(rval)->properties_info) > 0) {
+ if (obj && zend_hash_num_elements(&obj->ce->properties_info) > 0) {
zend_property_info *existing_propinfo;
zend_string *new_key;
const char *unmangled_class = NULL;
@@ -456,8 +463,8 @@ string_key:
unmangled = zend_string_init(unmangled_prop, unmangled_prop_len, 0);
- existing_propinfo = zend_hash_find_ptr(&Z_OBJCE_P(rval)->properties_info, unmangled);
- if ((unmangled_class == NULL || !strcmp(unmangled_class, "*") || !strcasecmp(unmangled_class, ZSTR_VAL(Z_OBJCE_P(rval)->name)))
+ existing_propinfo = zend_hash_find_ptr(&obj->ce->properties_info, unmangled);
+ if ((unmangled_class == NULL || !strcmp(unmangled_class, "*") || !strcasecmp(unmangled_class, ZSTR_VAL(obj->ce->name)))
&& (existing_propinfo != NULL)
&& (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) {
if (existing_propinfo->flags & ZEND_ACC_PROTECTED) {
@@ -491,9 +498,24 @@ string_key:
if ((old_data = zend_hash_find(ht, Z_STR(key))) != NULL) {
if (Z_TYPE_P(old_data) == IS_INDIRECT) {
old_data = Z_INDIRECT_P(old_data);
+ info = zend_get_typed_property_info_for_slot(obj, old_data);
+ var_push_dtor(var_hash, old_data);
+ data = zend_hash_update_ind(ht, Z_STR(key), &d);
+
+ if (UNEXPECTED(info)) {
+ /* Remember to which property this slot belongs, so we can add a
+ * type source if it is turned into a reference lateron. */
+ if (!(*var_hash)->ref_props) {
+ (*var_hash)->ref_props = emalloc(sizeof(HashTable));
+ zend_hash_init((*var_hash)->ref_props, 8, NULL, NULL, 0);
+ }
+ zend_hash_index_update_ptr(
+ (*var_hash)->ref_props, (zend_uintptr_t) data, info);
+ }
+ } else {
+ var_push_dtor(var_hash, old_data);
+ data = zend_hash_update_ind(ht, Z_STR(key), &d);
}
- var_push_dtor(var_hash, old_data);
- data = zend_hash_update_ind(ht, Z_STR(key), &d);
} else {
data = zend_hash_add_new(ht, Z_STR(key), &d);
}
@@ -512,6 +534,18 @@ string_key:
return 0;
}
+ if (UNEXPECTED(info)) {
+ if (!zend_verify_prop_assignable_by_ref(info, data, /* strict */ 1)) {
+ zval_ptr_dtor(data);
+ ZVAL_UNDEF(data);
+ zval_dtor(&key);
+ return 0;
+ }
+ if (Z_ISREF_P(data)) {
+ ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(data), info);
+ }
+ }
+
if (BG(unserialize).level > 1) {
var_push_dtor(var_hash, data);
}
@@ -613,7 +647,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements)
}
zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, HT_FLAGS(ht) & HASH_FLAG_PACKED);
- if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
+ if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, Z_OBJ_P(rval))) {
if (has_wakeup) {
ZVAL_DEREF(rval);
GC_ADD_FLAGS(Z_OBJ_P(rval), IS_OBJ_DESTRUCTOR_CALLED);
@@ -697,13 +731,19 @@ static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER, int as_key)
return 0;
}
- if (Z_ISREF_P(rval_ref)) {
- ZVAL_COPY(rval, rval_ref);
- } else {
+ if (!Z_ISREF_P(rval_ref)) {
+ zend_property_info *info = NULL;
+ if ((*var_hash)->ref_props) {
+ info = zend_hash_index_find_ptr((*var_hash)->ref_props, (zend_uintptr_t) rval_ref);
+ }
ZVAL_NEW_REF(rval_ref, rval_ref);
- ZVAL_COPY(rval, rval_ref);
+ if (info) {
+ ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(rval_ref), info);
+ }
}
+ ZVAL_COPY(rval, rval_ref);
+
return 1;
}
@@ -901,7 +941,7 @@ use_double:
* prohibit "r:" references to non-objects, as we only generate them for objects. */
HT_ALLOW_COW_VIOLATION(Z_ARRVAL_P(rval));
- if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, 0)) {
+ if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL_P(rval), elements, NULL)) {
return 0;
}
diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c
index a00b73ee8a..0f7726f334 100644
--- a/ext/sysvmsg/sysvmsg.c
+++ b/ext/sysvmsg/sysvmsg.c
@@ -318,7 +318,7 @@ PHP_FUNCTION(msg_remove_queue)
}
/* }}} */
-/* {{{ proto mixed msg_receive(resource queue, int desiredmsgtype, int &msgtype, int maxsize, mixed message [, bool unserialize=true [, int flags=0 [, int errorcode]]])
+/* {{{ proto mixed msg_receive(resource queue, int desiredmsgtype, int &msgtype, int maxsize, mixed &message [, bool unserialize=true [, int flags=0 [, int &errorcode]]])
Send a message of type msgtype (must be > 0) to a message queue */
PHP_FUNCTION(msg_receive)
{
@@ -332,7 +332,7 @@ PHP_FUNCTION(msg_receive)
RETVAL_FALSE;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz/lz/|blz/",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlzlz|blz",
&queue, &desiredmsgtype, &out_msgtype, &maxsize,
&out_message, &do_unserialize, &flags, &zerrcode) == FAILURE) {
return;
@@ -368,19 +368,12 @@ PHP_FUNCTION(msg_receive)
result = msgrcv(mq->id, messagebuffer, maxsize, desiredmsgtype, realflags);
- zval_ptr_dtor(out_msgtype);
- zval_ptr_dtor(out_message);
- ZVAL_LONG(out_msgtype, 0);
- ZVAL_FALSE(out_message);
-
- if (zerrcode) {
- zval_ptr_dtor(zerrcode);
- ZVAL_LONG(zerrcode, 0);
- }
-
if (result >= 0) {
/* got it! */
- ZVAL_LONG(out_msgtype, messagebuffer->mtype);
+ ZEND_TRY_ASSIGN_LONG(out_msgtype, messagebuffer->mtype);
+ if (zerrcode) {
+ ZEND_TRY_ASSIGN_LONG(zerrcode, 0);
+ }
RETVAL_TRUE;
if (do_unserialize) {
@@ -391,16 +384,21 @@ PHP_FUNCTION(msg_receive)
PHP_VAR_UNSERIALIZE_INIT(var_hash);
if (!php_var_unserialize(&tmp, &p, p + result, &var_hash)) {
php_error_docref(NULL, E_WARNING, "message corrupted");
+ ZEND_TRY_ASSIGN_FALSE(out_message);
RETVAL_FALSE;
} else {
- ZVAL_COPY_VALUE(out_message, &tmp);
+ ZEND_TRY_ASSIGN_VALUE(out_message, &tmp);
}
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
} else {
- ZVAL_STRINGL(out_message, messagebuffer->mtext, result);
+ ZEND_TRY_ASSIGN_STRINGL(out_message, messagebuffer->mtext, result);
+ }
+ } else {
+ ZEND_TRY_ASSIGN_LONG(out_msgtype, 0);
+ ZEND_TRY_ASSIGN_FALSE(out_message);
+ if (zerrcode) {
+ ZEND_TRY_ASSIGN_LONG(zerrcode, errno);
}
- } else if (zerrcode) {
- ZVAL_LONG(zerrcode, errno);
}
efree(messagebuffer);
}
@@ -420,7 +418,7 @@ PHP_FUNCTION(msg_send)
RETVAL_FALSE;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz|bbz/",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rlz|bbz",
&queue, &msgtype, &message, &do_serialize, &blocking, &zerror) == FAILURE) {
return;
}
@@ -486,8 +484,7 @@ PHP_FUNCTION(msg_send)
if (result == -1) {
php_error_docref(NULL, E_WARNING, "msgsnd failed: %s", strerror(errno));
if (zerror) {
- zval_ptr_dtor(zerror);
- ZVAL_LONG(zerror, errno);
+ ZEND_TRY_ASSIGN_LONG(zerror, errno);
}
} else {
RETVAL_TRUE;
diff --git a/ext/xml/xml.c b/ext/xml/xml.c
index 9868c5e3c4..d5f2a51312 100644
--- a/ext/xml/xml.c
+++ b/ext/xml/xml.c
@@ -1434,21 +1434,25 @@ PHP_FUNCTION(xml_parse_into_struct)
size_t data_len;
int ret;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz/|z/", &pind, &data, &data_len, &xdata, &info) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsz|z", &pind, &data, &data_len, &xdata, &info) == FAILURE) {
return;
}
if (info) {
- zval_ptr_dtor(info);
- array_init(info);
+ info = zend_try_array_init(info);
+ if (!info) {
+ return;
+ }
}
if ((parser = (xml_parser *)zend_fetch_resource(Z_RES_P(pind), "XML Parser", le_xml_parser)) == NULL) {
RETURN_FALSE;
}
- zval_ptr_dtor(xdata);
- array_init(xdata);
+ xdata = zend_try_array_init(xdata);
+ if (!xdata) {
+ return;
+ }
ZVAL_COPY_VALUE(&parser->data, xdata);
diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c
index ba5c854aee..2710be98c6 100644
--- a/ext/xmlreader/php_xmlreader.c
+++ b/ext/xmlreader/php_xmlreader.c
@@ -181,7 +181,7 @@ zval *xmlreader_read_property(zval *object, zval *member, int type, void **cache
/* }}} */
/* {{{ xmlreader_write_property */
-void xmlreader_write_property(zval *object, zval *member, zval *value, void **cache_slot)
+zval *xmlreader_write_property(zval *object, zval *member, zval *value, void **cache_slot)
{
xmlreader_object *obj;
zval tmp_member;
@@ -200,12 +200,14 @@ void xmlreader_write_property(zval *object, zval *member, zval *value, void **ca
if (hnd != NULL) {
php_error_docref(NULL, E_WARNING, "Cannot write to read-only property");
} else {
- zend_std_write_property(object, member, value, cache_slot);
+ value = zend_std_write_property(object, member, value, cache_slot);
}
if (member == &tmp_member) {
zval_ptr_dtor_str(&tmp_member);
}
+
+ return value;
}
/* }}} */
diff --git a/ext/xmlrpc/xmlrpc-epi-php.c b/ext/xmlrpc/xmlrpc-epi-php.c
index 737a3f84a5..937f7b1b0f 100644
--- a/ext/xmlrpc/xmlrpc-epi-php.c
+++ b/ext/xmlrpc/xmlrpc-epi-php.c
@@ -764,11 +764,9 @@ void decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval
if (method_name_out) {
method_name = XMLRPC_RequestGetMethodName(response);
if (method_name) {
- zval_ptr_dtor(method_name_out);
- ZVAL_STRING(method_name_out, method_name);
+ ZEND_TRY_ASSIGN_STRING(method_name_out, method_name);
} else {
- zval_ptr_dtor(retval);
- ZVAL_NULL(retval);
+ ZEND_TRY_ASSIGN_NULL(retval);
}
}
}
@@ -787,7 +785,7 @@ PHP_FUNCTION(xmlrpc_decode_request)
zval *method;
size_t xml_len, encoding_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) {
return;
}
@@ -1389,15 +1387,19 @@ PHP_FUNCTION(xmlrpc_set_type)
size_t type_len;
XMLRPC_VALUE_TYPE vtype;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/s", &arg, &type, &type_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zs", &arg, &type, &type_len) == FAILURE) {
return;
}
vtype = xmlrpc_str_as_type(type);
if (vtype != xmlrpc_none) {
- if (set_zval_xmlrpc_type(arg, vtype) == SUCCESS) {
+ zval tmp;
+ ZVAL_COPY(&tmp, Z_REFVAL_P(arg));
+ if (set_zval_xmlrpc_type(&tmp, vtype) == SUCCESS) {
+ ZEND_TRY_ASSIGN_VALUE(arg, &tmp);
RETURN_TRUE;
}
+ Z_TRY_DELREF(tmp);
} else {
zend_error(E_WARNING,"invalid type '%s' passed to xmlrpc_set_type()", type);
}
diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
index 31455daab8..8d533b7907 100644
--- a/ext/zend_test/test.c
+++ b/ext/zend_test/test.c
@@ -137,6 +137,7 @@ ZEND_FUNCTION(zend_leak_variable)
static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ {
zend_object *obj = zend_objects_new(class_type);
+ object_properties_init(obj, class_type);
obj->handlers = &zend_test_class_handlers;
return obj;
}
@@ -203,6 +204,36 @@ PHP_MINIT_FUNCTION(zend_test)
zend_declare_property_null(zend_test_class, "_StaticProp", sizeof("_StaticProp") - 1, ZEND_ACC_STATIC);
+ {
+ zend_string *name = zend_string_init("intProp", sizeof("intProp") - 1, 1);
+ zval val;
+ ZVAL_LONG(&val, 123);
+ zend_declare_typed_property(
+ zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL, ZEND_TYPE_ENCODE(IS_LONG, 0));
+ zend_string_release(name);
+ }
+
+ {
+ zend_string *name = zend_string_init("classProp", sizeof("classProp") - 1, 1);
+ zend_string *class_name = zend_string_init("stdClass", sizeof("stdClass") - 1, 1);
+ zval val;
+ ZVAL_NULL(&val);
+ zend_declare_typed_property(
+ zend_test_class, name, &val, ZEND_ACC_PUBLIC, NULL,
+ ZEND_TYPE_ENCODE_CLASS(class_name, 1));
+ zend_string_release(name);
+ }
+
+ {
+ zend_string *name = zend_string_init("staticIntProp", sizeof("staticIntProp") - 1, 1);
+ zval val;
+ ZVAL_LONG(&val, 123);
+ zend_declare_typed_property(
+ zend_test_class, name, &val, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, NULL,
+ ZEND_TYPE_ENCODE(IS_LONG, 0));
+ zend_string_release(name);
+ }
+
INIT_CLASS_ENTRY(class_entry, "_ZendTestChildClass", NULL);
zend_test_child_class = zend_register_internal_class_ex(&class_entry, zend_test_class);
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 5aa17fb669..dbc6c1603e 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -2133,7 +2133,7 @@ static ZIPARCHIVE_METHOD(getExternalAttributesName)
ZIP_FROM_OBJECT(intern, self);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz/z/|l",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "szz|l",
&name, &name_len, &z_opsys, &z_attr, &flags) == FAILURE) {
return;
}
@@ -2150,10 +2150,8 @@ static ZIPARCHIVE_METHOD(getExternalAttributesName)
(zip_flags_t)flags, &opsys, &attr) < 0) {
RETURN_FALSE;
}
- zval_ptr_dtor(z_opsys);
- ZVAL_LONG(z_opsys, opsys);
- zval_ptr_dtor(z_attr);
- ZVAL_LONG(z_attr, attr);
+ ZEND_TRY_ASSIGN_LONG(z_opsys, opsys);
+ ZEND_TRY_ASSIGN_LONG(z_attr, attr);
RETURN_TRUE;
}
/* }}} */
@@ -2171,7 +2169,7 @@ static ZIPARCHIVE_METHOD(getExternalAttributesIndex)
ZIP_FROM_OBJECT(intern, self);
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/z/|l",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "lzz|l",
&index, &z_opsys, &z_attr, &flags) == FAILURE) {
return;
}
@@ -2181,10 +2179,8 @@ static ZIPARCHIVE_METHOD(getExternalAttributesIndex)
(zip_flags_t)flags, &opsys, &attr) < 0) {
RETURN_FALSE;
}
- zval_ptr_dtor(z_opsys);
- ZVAL_LONG(z_opsys, opsys);
- zval_ptr_dtor(z_attr);
- ZVAL_LONG(z_attr, attr);
+ ZEND_TRY_ASSIGN_LONG(z_opsys, opsys);
+ ZEND_TRY_ASSIGN_LONG(z_attr, attr);
RETURN_TRUE;
}
/* }}} */