@@ -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,6 +669,10 @@ 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 ;
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 )) {
675
+ return 0 ;
669
676
}
670
677
671
678
/* References to objects are treated as if the reference didn't exist */
@@ -921,7 +928,7 @@ static int php_var_serialize_get_sleep_props(
921
928
}
922
929
/* }}} */
923
930
924
- 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 ) /* {{{ */
925
932
{
926
933
smart_str_append_unsigned (buf , count );
927
934
smart_str_appendl (buf , ":{" , 2 );
@@ -951,19 +958,19 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable
951
958
if (Z_TYPE_P (data ) == IS_ARRAY ) {
952
959
if (UNEXPECTED (Z_IS_RECURSIVE_P (data ))
953
960
|| UNEXPECTED (Z_TYPE_P (struc ) == IS_ARRAY && Z_ARR_P (data ) == Z_ARR_P (struc ))) {
954
- php_add_var_hash (var_hash , struc );
961
+ php_add_var_hash (var_hash , struc , in_rcn_array );
955
962
smart_str_appendl (buf , "N;" , 2 );
956
963
} else {
957
964
if (Z_REFCOUNTED_P (data )) {
958
965
Z_PROTECT_RECURSION_P (data );
959
966
}
960
- php_var_serialize_intern (buf , data , var_hash );
967
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
961
968
if (Z_REFCOUNTED_P (data )) {
962
969
Z_UNPROTECT_RECURSION_P (data );
963
970
}
964
971
}
965
972
} else {
966
- php_var_serialize_intern (buf , data , var_hash );
973
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
967
974
}
968
975
} ZEND_HASH_FOREACH_END ();
969
976
}
@@ -978,13 +985,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht,
978
985
if (php_var_serialize_get_sleep_props (& props , struc , ht ) == SUCCESS ) {
979
986
php_var_serialize_class_name (buf , struc );
980
987
php_var_serialize_nested_data (
981
- 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 );
982
989
}
983
990
zend_hash_destroy (& props );
984
991
}
985
992
/* }}} */
986
993
987
- 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 ) /* {{{ */
988
995
{
989
996
zend_long var_already ;
990
997
HashTable * myht ;
@@ -993,7 +1000,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
993
1000
return ;
994
1001
}
995
1002
996
- 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 ))) {
997
1004
if (var_already == -1 ) {
998
1005
/* Reference to an object that failed to serialize, replace with null. */
999
1006
smart_str_appendl (buf , "N;" , 2 );
@@ -1102,7 +1109,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1102
1109
if (Z_ISREF_P (data ) && Z_REFCOUNT_P (data ) == 1 ) {
1103
1110
data = Z_REFVAL_P (data );
1104
1111
}
1105
- php_var_serialize_intern (buf , data , var_hash );
1112
+ php_var_serialize_intern (buf , data , var_hash , Z_REFCOUNT ( retval ) > 1 , false );
1106
1113
} ZEND_HASH_FOREACH_END ();
1107
1114
smart_str_appendc (buf , '}' );
1108
1115
@@ -1224,7 +1231,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1224
1231
prop = Z_REFVAL_P (prop );
1225
1232
}
1226
1233
1227
- php_var_serialize_intern (buf , prop , var_hash );
1234
+ php_var_serialize_intern (buf , prop , var_hash , false, false );
1228
1235
}
1229
1236
smart_str_appendc (buf , '}' );
1230
1237
} else {
@@ -1239,15 +1246,16 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1239
1246
if (count > 0 && incomplete_class ) {
1240
1247
-- count ;
1241
1248
}
1242
- 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 );
1243
1250
zend_release_properties (myht );
1244
1251
return ;
1245
1252
}
1246
1253
case IS_ARRAY :
1247
1254
smart_str_appendl (buf , "a:" , 2 );
1248
1255
myht = Z_ARRVAL_P (struc );
1249
1256
php_var_serialize_nested_data (
1250
- 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 ));
1251
1259
return ;
1252
1260
case IS_REFERENCE :
1253
1261
struc = Z_REFVAL_P (struc );
@@ -1261,7 +1269,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1261
1269
1262
1270
PHPAPI void php_var_serialize (smart_str * buf , zval * struc , php_serialize_data_t * data ) /* {{{ */
1263
1271
{
1264
- php_var_serialize_intern (buf , struc , * data );
1272
+ php_var_serialize_intern (buf , struc , * data , false, true );
1265
1273
smart_str_0 (buf );
1266
1274
}
1267
1275
/* }}} */
0 commit comments