@@ -652,9 +652,12 @@ PHP_FUNCTION(var_export)
652
652
}
653
653
/* }}} */
654
654
655
- static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash );
655
+ static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash , bool in_rcn_array , bool is_root );
656
656
657
- static inline zend_long php_add_var_hash (php_serialize_data_t data , zval * var ) /* {{{ */
657
+ /**
658
+ * @param bool in_rcn_array Whether the element appears in a potentially nested array with RC > 1.
659
+ */
660
+ static inline zend_long php_add_var_hash (php_serialize_data_t data , zval * var , bool in_rcn_array ) /* {{{ */
658
661
{
659
662
zval * zv ;
660
663
zend_ulong key ;
@@ -666,7 +669,9 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var) /
666
669
/* pass */
667
670
} else if (Z_TYPE_P (var ) != IS_OBJECT ) {
668
671
return 0 ;
669
- } else if (Z_REFCOUNT_P (var ) == 1 && (Z_OBJ_P (var )-> properties == NULL || GC_REFCOUNT (Z_OBJ_P (var )-> properties ) == 1 )) {
672
+ } else if (!in_rcn_array
673
+ && Z_REFCOUNT_P (var ) == 1
674
+ && (Z_OBJ_P (var )-> properties == NULL || GC_REFCOUNT (Z_OBJ_P (var )-> properties ) == 1 )) {
670
675
return 0 ;
671
676
}
672
677
@@ -923,7 +928,7 @@ static int php_var_serialize_get_sleep_props(
923
928
}
924
929
/* }}} */
925
930
926
- static void php_var_serialize_nested_data (smart_str * buf , zval * struc , HashTable * ht , uint32_t count , bool incomplete_class , php_serialize_data_t var_hash ) /* {{{ */
931
+ static void php_var_serialize_nested_data (smart_str * buf , zval * struc , HashTable * ht , uint32_t count , bool incomplete_class , php_serialize_data_t var_hash , bool in_rcn_array ) /* {{{ */
927
932
{
928
933
smart_str_append_unsigned (buf , count );
929
934
smart_str_appendl (buf , ":{" , 2 );
@@ -953,19 +958,19 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable
953
958
if (Z_TYPE_P (data ) == IS_ARRAY ) {
954
959
if (UNEXPECTED (Z_IS_RECURSIVE_P (data ))
955
960
|| UNEXPECTED (Z_TYPE_P (struc ) == IS_ARRAY && Z_ARR_P (data ) == Z_ARR_P (struc ))) {
956
- php_add_var_hash (var_hash , struc );
961
+ php_add_var_hash (var_hash , struc , in_rcn_array );
957
962
smart_str_appendl (buf , "N;" , 2 );
958
963
} else {
959
964
if (Z_REFCOUNTED_P (data )) {
960
965
Z_PROTECT_RECURSION_P (data );
961
966
}
962
- php_var_serialize_intern (buf , data , var_hash );
967
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
963
968
if (Z_REFCOUNTED_P (data )) {
964
969
Z_UNPROTECT_RECURSION_P (data );
965
970
}
966
971
}
967
972
} else {
968
- php_var_serialize_intern (buf , data , var_hash );
973
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
969
974
}
970
975
} ZEND_HASH_FOREACH_END ();
971
976
}
@@ -980,13 +985,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht,
980
985
if (php_var_serialize_get_sleep_props (& props , struc , ht ) == SUCCESS ) {
981
986
php_var_serialize_class_name (buf , struc );
982
987
php_var_serialize_nested_data (
983
- buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash );
988
+ buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash , GC_REFCOUNT ( & props ) > 1 );
984
989
}
985
990
zend_hash_destroy (& props );
986
991
}
987
992
/* }}} */
988
993
989
- static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash ) /* {{{ */
994
+ static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash , bool in_rcn_array , bool is_root ) /* {{{ */
990
995
{
991
996
zend_long var_already ;
992
997
HashTable * myht ;
@@ -995,7 +1000,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
995
1000
return ;
996
1001
}
997
1002
998
- if (var_hash && (var_already = php_add_var_hash (var_hash , struc ))) {
1003
+ if (var_hash && (var_already = php_add_var_hash (var_hash , struc , in_rcn_array ))) {
999
1004
if (var_already == -1 ) {
1000
1005
/* Reference to an object that failed to serialize, replace with null. */
1001
1006
smart_str_appendl (buf , "N;" , 2 );
@@ -1104,7 +1109,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1104
1109
if (Z_ISREF_P (data ) && Z_REFCOUNT_P (data ) == 1 ) {
1105
1110
data = Z_REFVAL_P (data );
1106
1111
}
1107
- php_var_serialize_intern (buf , data , var_hash );
1112
+ php_var_serialize_intern (buf , data , var_hash , Z_REFCOUNT ( retval ) > 1 , false );
1108
1113
} ZEND_HASH_FOREACH_END ();
1109
1114
smart_str_appendc (buf , '}' );
1110
1115
@@ -1226,7 +1231,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1226
1231
prop = Z_REFVAL_P (prop );
1227
1232
}
1228
1233
1229
- php_var_serialize_intern (buf , prop , var_hash );
1234
+ php_var_serialize_intern (buf , prop , var_hash , false, false );
1230
1235
}
1231
1236
smart_str_appendc (buf , '}' );
1232
1237
} else {
@@ -1241,15 +1246,16 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1241
1246
if (count > 0 && incomplete_class ) {
1242
1247
-- count ;
1243
1248
}
1244
- php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash );
1249
+ php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash , GC_REFCOUNT ( myht ) > 1 );
1245
1250
zend_release_properties (myht );
1246
1251
return ;
1247
1252
}
1248
1253
case IS_ARRAY :
1249
1254
smart_str_appendl (buf , "a:" , 2 );
1250
1255
myht = Z_ARRVAL_P (struc );
1251
1256
php_var_serialize_nested_data (
1252
- buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash );
1257
+ buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash ,
1258
+ !is_root && (in_rcn_array || GC_REFCOUNT (myht ) > 1 ));
1253
1259
return ;
1254
1260
case IS_REFERENCE :
1255
1261
struc = Z_REFVAL_P (struc );
@@ -1263,7 +1269,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1263
1269
1264
1270
PHPAPI void php_var_serialize (smart_str * buf , zval * struc , php_serialize_data_t * data ) /* {{{ */
1265
1271
{
1266
- php_var_serialize_intern (buf , struc , * data );
1272
+ php_var_serialize_intern (buf , struc , * data , false, true );
1267
1273
smart_str_0 (buf );
1268
1274
}
1269
1275
/* }}} */
0 commit comments