@@ -655,9 +655,12 @@ PHP_FUNCTION(var_export)
655
655
}
656
656
/* }}} */
657
657
658
- static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash );
658
+ static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash , bool in_rcn_array , bool is_root );
659
659
660
- static inline zend_long php_add_var_hash (php_serialize_data_t data , zval * var ) /* {{{ */
660
+ /**
661
+ * @param bool in_rcn_array Whether the element appears in a potentially nested array with RC > 1.
662
+ */
663
+ static inline zend_long php_add_var_hash (php_serialize_data_t data , zval * var , bool in_rcn_array ) /* {{{ */
661
664
{
662
665
zval * zv ;
663
666
zend_ulong key ;
@@ -669,7 +672,9 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var) /
669
672
/* pass */
670
673
} else if (Z_TYPE_P (var ) != IS_OBJECT ) {
671
674
return 0 ;
672
- } else if (Z_REFCOUNT_P (var ) == 1 && (Z_OBJ_P (var )-> properties == NULL || GC_REFCOUNT (Z_OBJ_P (var )-> properties ) == 1 )) {
675
+ } else if (!in_rcn_array
676
+ && Z_REFCOUNT_P (var ) == 1
677
+ && (Z_OBJ_P (var )-> properties == NULL || GC_REFCOUNT (Z_OBJ_P (var )-> properties ) == 1 )) {
673
678
return 0 ;
674
679
}
675
680
@@ -911,7 +916,7 @@ static int php_var_serialize_get_sleep_props(
911
916
}
912
917
/* }}} */
913
918
914
- 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 ) /* {{{ */
919
+ 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 ) /* {{{ */
915
920
{
916
921
smart_str_append_unsigned (buf , count );
917
922
smart_str_appendl (buf , ":{" , 2 );
@@ -941,19 +946,19 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable
941
946
if (Z_TYPE_P (data ) == IS_ARRAY ) {
942
947
if (UNEXPECTED (Z_IS_RECURSIVE_P (data ))
943
948
|| UNEXPECTED (Z_TYPE_P (struc ) == IS_ARRAY && Z_ARR_P (data ) == Z_ARR_P (struc ))) {
944
- php_add_var_hash (var_hash , struc );
949
+ php_add_var_hash (var_hash , struc , in_rcn_array );
945
950
smart_str_appendl (buf , "N;" , 2 );
946
951
} else {
947
952
if (Z_REFCOUNTED_P (data )) {
948
953
Z_PROTECT_RECURSION_P (data );
949
954
}
950
- php_var_serialize_intern (buf , data , var_hash );
955
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
951
956
if (Z_REFCOUNTED_P (data )) {
952
957
Z_UNPROTECT_RECURSION_P (data );
953
958
}
954
959
}
955
960
} else {
956
- php_var_serialize_intern (buf , data , var_hash );
961
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
957
962
}
958
963
} ZEND_HASH_FOREACH_END ();
959
964
}
@@ -968,13 +973,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht,
968
973
if (php_var_serialize_get_sleep_props (& props , struc , ht ) == SUCCESS ) {
969
974
php_var_serialize_class_name (buf , struc );
970
975
php_var_serialize_nested_data (
971
- buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash );
976
+ buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash , GC_REFCOUNT ( & props ) > 1 );
972
977
}
973
978
zend_hash_destroy (& props );
974
979
}
975
980
/* }}} */
976
981
977
- static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash ) /* {{{ */
982
+ static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash , bool in_rcn_array , bool is_root ) /* {{{ */
978
983
{
979
984
zend_long var_already ;
980
985
HashTable * myht ;
@@ -983,7 +988,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
983
988
return ;
984
989
}
985
990
986
- if (var_hash && (var_already = php_add_var_hash (var_hash , struc ))) {
991
+ if (var_hash && (var_already = php_add_var_hash (var_hash , struc , in_rcn_array ))) {
987
992
if (var_already == -1 ) {
988
993
/* Reference to an object that failed to serialize, replace with null. */
989
994
smart_str_appendl (buf , "N;" , 2 );
@@ -1092,7 +1097,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1092
1097
if (Z_ISREF_P (data ) && Z_REFCOUNT_P (data ) == 1 ) {
1093
1098
data = Z_REFVAL_P (data );
1094
1099
}
1095
- php_var_serialize_intern (buf , data , var_hash );
1100
+ php_var_serialize_intern (buf , data , var_hash , Z_REFCOUNT ( retval ) > 1 , false );
1096
1101
} ZEND_HASH_FOREACH_END ();
1097
1102
smart_str_appendc (buf , '}' );
1098
1103
@@ -1214,7 +1219,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1214
1219
prop = Z_REFVAL_P (prop );
1215
1220
}
1216
1221
1217
- php_var_serialize_intern (buf , prop , var_hash );
1222
+ php_var_serialize_intern (buf , prop , var_hash , false, false );
1218
1223
}
1219
1224
smart_str_appendc (buf , '}' );
1220
1225
} else {
@@ -1229,15 +1234,16 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1229
1234
if (count > 0 && incomplete_class ) {
1230
1235
-- count ;
1231
1236
}
1232
- php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash );
1237
+ php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash , GC_REFCOUNT ( myht ) > 1 );
1233
1238
zend_release_properties (myht );
1234
1239
return ;
1235
1240
}
1236
1241
case IS_ARRAY :
1237
1242
smart_str_appendl (buf , "a:" , 2 );
1238
1243
myht = Z_ARRVAL_P (struc );
1239
1244
php_var_serialize_nested_data (
1240
- buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash );
1245
+ buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash ,
1246
+ !is_root && (in_rcn_array || GC_REFCOUNT (myht ) > 1 ));
1241
1247
return ;
1242
1248
case IS_REFERENCE :
1243
1249
struc = Z_REFVAL_P (struc );
@@ -1251,7 +1257,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1251
1257
1252
1258
PHPAPI void php_var_serialize (smart_str * buf , zval * struc , php_serialize_data_t * data ) /* {{{ */
1253
1259
{
1254
- php_var_serialize_intern (buf , struc , * data );
1260
+ php_var_serialize_intern (buf , struc , * data , false, true );
1255
1261
smart_str_0 (buf );
1256
1262
}
1257
1263
/* }}} */
0 commit comments