From c7a37e12b7f39ea652b4ac8794f4663024d2a57a Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Thu, 5 Jul 2018 22:02:59 +0200 Subject: [PATCH] Export stdClass objects using (object) cast (fixes #48016) Before this change, var_export()'s output for stdClass objects calls the non-existent stdClass::__set_state method, and is therefore useless. This commit makes var_export() output an (object) cast from an array instead, which when evaluated, will produce a stdClass object. Other classes see unchanged output. --- NEWS | 1 + UPGRADING | 5 +++++ ext/intl/tests/dateformat_format.phpt | 20 +++++++++---------- .../tests/dateformat_format_variant3.phpt | 20 +++++++++---------- ext/standard/tests/array/var_export.phpt | 4 ++-- .../general_functions/var_export-locale.phpt | 12 +++++------ .../general_functions/var_export_basic6.phpt | 12 +++++------ .../general_functions/var_export_basic8.phpt | 16 +++++++-------- .../general_functions/var_export_basic9.phpt | 4 ++-- ext/standard/var.c | 15 +++++++++++--- 10 files changed, 62 insertions(+), 47 deletions(-) diff --git a/NEWS b/NEWS index cc0bd6c21176d..4a3e80c5df72b 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,7 @@ PHP NEWS . Fixed bug #76505 (array_merge_recursive() is duplicating sub-array keys). (Laruence) . Fixed bug #71848 (getimagesize with $imageinfo returns false). (cmb) + . Fixed bug #48016 (stdClass::__setState is not defined although var_export() uses it). (Andrea) - Tokenizer: . Fixed bug #76538 (token_get_all with TOKEN_PARSE flag fails to recognise diff --git a/UPGRADING b/UPGRADING index c02d315422fd7..97415fdcaa5c6 100644 --- a/UPGRADING +++ b/UPGRADING @@ -356,6 +356,11 @@ PCRE: behavioral changes, and augments the existing regular expression syntax. See for details. + Standard: + . var_export() now exports stdClass objects as an array casted to an object + (`(object) array( ... )`), rather than using the nonexistent method + stdClass::__setState(). + ZIP: . Bundled libzip has been dropped, system library is now required. diff --git a/ext/intl/tests/dateformat_format.phpt b/ext/intl/tests/dateformat_format.phpt index a0135a809cc12..cc1682ddd2f73 100644 --- a/ext/intl/tests/dateformat_format.phpt +++ b/ext/intl/tests/dateformat_format.phpt @@ -397,27 +397,27 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 20001230 05:04 PM ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' diff --git a/ext/intl/tests/dateformat_format_variant3.phpt b/ext/intl/tests/dateformat_format_variant3.phpt index da0d662ca7916..6827e8132ac07 100644 --- a/ext/intl/tests/dateformat_format_variant3.phpt +++ b/ext/intl/tests/dateformat_format_variant3.phpt @@ -397,27 +397,27 @@ Date is: DateTime::__set_state(array( ------------ Formatted DateTime is : 20001230 05:04 PM ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' ------------ -Date is: stdClass::__set_state(array( -)) +Date is: (object) array( +) ------------ Error while formatting as: 'datefmt_format: invalid object type for date/time (only IntlCalendar and DateTimeInterface permitted): U_ILLEGAL_ARGUMENT_ERROR' diff --git a/ext/standard/tests/array/var_export.phpt b/ext/standard/tests/array/var_export.phpt index 0b1f76094db9e..5c23ad267c109 100644 --- a/ext/standard/tests/array/var_export.phpt +++ b/ext/standard/tests/array/var_export.phpt @@ -6,8 +6,8 @@ $a = (object) array (1, 3, "foo" => "bar"); var_export($a); ?> --EXPECT-- -stdClass::__set_state(array( +(object) array( '0' => 1, '1' => 3, 'foo' => 'bar', -)) +) diff --git a/ext/standard/tests/general_functions/var_export-locale.phpt b/ext/standard/tests/general_functions/var_export-locale.phpt index 11db6fbbb48ef..e440238970adc 100644 --- a/ext/standard/tests/general_functions/var_export-locale.phpt +++ b/ext/standard/tests/general_functions/var_export-locale.phpt @@ -914,12 +914,12 @@ string(41) "array ( *** Output for objects *** Iteration 1 -stdClass::__set_state(array( -)) -stdClass::__set_state(array( -)) -string(31) "stdClass::__set_state(array( -))" +(object) array( +) +(object) array( +) +string(17) "(object) array( +)" Iteration 2 diff --git a/ext/standard/tests/general_functions/var_export_basic6.phpt b/ext/standard/tests/general_functions/var_export_basic6.phpt index 38fdb373dfc5d..bdcdf48c02e45 100644 --- a/ext/standard/tests/general_functions/var_export_basic6.phpt +++ b/ext/standard/tests/general_functions/var_export_basic6.phpt @@ -108,12 +108,12 @@ foreach($valid_objects as $key => $obj) { *** Output for objects *** -- Iteration: new stdclass -- -stdClass::__set_state(array( -)) -stdClass::__set_state(array( -)) -string(31) "stdClass::__set_state(array( -))" +(object) array( +) +(object) array( +) +string(17) "(object) array( +)" -- Iteration: new foo -- diff --git a/ext/standard/tests/general_functions/var_export_basic8.phpt b/ext/standard/tests/general_functions/var_export_basic8.phpt index f71c095f968a4..faae2bca17a0d 100644 --- a/ext/standard/tests/general_functions/var_export_basic8.phpt +++ b/ext/standard/tests/general_functions/var_export_basic8.phpt @@ -30,17 +30,17 @@ var_export($b); ===DONE=== --EXPECT-- -- Var export on a simple object -- -stdClass::__set_state(array( +(object) array( 'a' => 1, 'b' => array ( 'k' => 2, ), 'x' => - stdClass::__set_state(array( + (object) array( 'p' => '22', - )), -)) + ), +) -- Var export on an simple array -- array ( @@ -57,15 +57,15 @@ array ( 'one' => 'first', ), 'bar' => - stdClass::__set_state(array( + (object) array( 'a' => 1, 'b' => array ( 'k' => 2, ), 'x' => - stdClass::__set_state(array( + (object) array( 'p' => '22', - )), - )), + ), + ), )===DONE=== diff --git a/ext/standard/tests/general_functions/var_export_basic9.phpt b/ext/standard/tests/general_functions/var_export_basic9.phpt index 3c9706edfd0d8..fd78c18c8e9a4 100644 --- a/ext/standard/tests/general_functions/var_export_basic9.phpt +++ b/ext/standard/tests/general_functions/var_export_basic9.phpt @@ -6,6 +6,6 @@ Bug #55082: var_export() doesn't escape properties properly $x->{'\'\\'} = 7; echo var_export($x); --EXPECT-- -stdClass::__set_state(array( +(object) array( '\'\\' => 7, -)) +) diff --git a/ext/standard/var.c b/ext/standard/var.c index 46d1b2df65cb2..7b1cb5949a580 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -527,8 +527,13 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */ buffer_append_spaces(buf, level - 1); } - smart_str_append(buf, Z_OBJCE_P(struc)->name); - smart_str_appendl(buf, "::__set_state(array(\n", 21); + /* stdClass has no __set_state method, but can be casted to */ + if (Z_OBJCE_P(struc) == zend_standard_class_def) { + smart_str_appendl(buf, "(object) array(\n", 16); + } else { + smart_str_append(buf, Z_OBJCE_P(struc)->name); + smart_str_appendl(buf, "::__set_state(array(\n", 21); + } if (myht) { ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) { @@ -539,7 +544,11 @@ PHPAPI void php_var_export_ex(zval *struc, int level, smart_str *buf) /* {{{ */ if (level > 1) { buffer_append_spaces(buf, level - 1); } - smart_str_appendl(buf, "))", 2); + if (Z_OBJCE_P(struc) == zend_standard_class_def) { + smart_str_appendc(buf, ')'); + } else { + smart_str_appendl(buf, "))", 2); + } break; case IS_REFERENCE: