@@ -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
@@ -926,7 +931,7 @@ static int php_var_serialize_get_sleep_props(
926
931
}
927
932
/* }}} */
928
933
929
- 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 ) /* {{{ */
934
+ 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 ) /* {{{ */
930
935
{
931
936
smart_str_append_unsigned (buf , count );
932
937
smart_str_appendl (buf , ":{" , 2 );
@@ -956,19 +961,19 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable
956
961
if (Z_TYPE_P (data ) == IS_ARRAY ) {
957
962
if (UNEXPECTED (Z_IS_RECURSIVE_P (data ))
958
963
|| UNEXPECTED (Z_TYPE_P (struc ) == IS_ARRAY && Z_ARR_P (data ) == Z_ARR_P (struc ))) {
959
- php_add_var_hash (var_hash , struc );
964
+ php_add_var_hash (var_hash , struc , in_rcn_array );
960
965
smart_str_appendl (buf , "N;" , 2 );
961
966
} else {
962
967
if (Z_REFCOUNTED_P (data )) {
963
968
Z_PROTECT_RECURSION_P (data );
964
969
}
965
- php_var_serialize_intern (buf , data , var_hash );
970
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
966
971
if (Z_REFCOUNTED_P (data )) {
967
972
Z_UNPROTECT_RECURSION_P (data );
968
973
}
969
974
}
970
975
} else {
971
- php_var_serialize_intern (buf , data , var_hash );
976
+ php_var_serialize_intern (buf , data , var_hash , in_rcn_array , false );
972
977
}
973
978
} ZEND_HASH_FOREACH_END ();
974
979
}
@@ -983,13 +988,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, HashTable *ht,
983
988
if (php_var_serialize_get_sleep_props (& props , struc , ht ) == SUCCESS ) {
984
989
php_var_serialize_class_name (buf , struc );
985
990
php_var_serialize_nested_data (
986
- buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash );
991
+ buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash , GC_REFCOUNT ( & props ) > 1 );
987
992
}
988
993
zend_hash_destroy (& props );
989
994
}
990
995
/* }}} */
991
996
992
- static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash ) /* {{{ */
997
+ static void php_var_serialize_intern (smart_str * buf , zval * struc , php_serialize_data_t var_hash , bool in_rcn_array , bool is_root ) /* {{{ */
993
998
{
994
999
zend_long var_already ;
995
1000
HashTable * myht ;
@@ -998,7 +1003,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
998
1003
return ;
999
1004
}
1000
1005
1001
- if (var_hash && (var_already = php_add_var_hash (var_hash , struc ))) {
1006
+ if (var_hash && (var_already = php_add_var_hash (var_hash , struc , in_rcn_array ))) {
1002
1007
if (var_already == -1 ) {
1003
1008
/* Reference to an object that failed to serialize, replace with null. */
1004
1009
smart_str_appendl (buf , "N;" , 2 );
@@ -1107,7 +1112,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1107
1112
if (Z_ISREF_P (data ) && Z_REFCOUNT_P (data ) == 1 ) {
1108
1113
data = Z_REFVAL_P (data );
1109
1114
}
1110
- php_var_serialize_intern (buf , data , var_hash );
1115
+ php_var_serialize_intern (buf , data , var_hash , Z_REFCOUNT ( retval ) > 1 , false );
1111
1116
} ZEND_HASH_FOREACH_END ();
1112
1117
smart_str_appendc (buf , '}' );
1113
1118
@@ -1229,7 +1234,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1229
1234
prop = Z_REFVAL_P (prop );
1230
1235
}
1231
1236
1232
- php_var_serialize_intern (buf , prop , var_hash );
1237
+ php_var_serialize_intern (buf , prop , var_hash , false, false );
1233
1238
}
1234
1239
smart_str_appendc (buf , '}' );
1235
1240
} else {
@@ -1244,15 +1249,16 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1244
1249
if (count > 0 && incomplete_class ) {
1245
1250
-- count ;
1246
1251
}
1247
- php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash );
1252
+ php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash , GC_REFCOUNT ( myht ) > 1 );
1248
1253
zend_release_properties (myht );
1249
1254
return ;
1250
1255
}
1251
1256
case IS_ARRAY :
1252
1257
smart_str_appendl (buf , "a:" , 2 );
1253
1258
myht = Z_ARRVAL_P (struc );
1254
1259
php_var_serialize_nested_data (
1255
- buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash );
1260
+ buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash ,
1261
+ !is_root && (in_rcn_array || GC_REFCOUNT (myht ) > 1 ));
1256
1262
return ;
1257
1263
case IS_REFERENCE :
1258
1264
struc = Z_REFVAL_P (struc );
@@ -1266,7 +1272,7 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1266
1272
1267
1273
PHPAPI void php_var_serialize (smart_str * buf , zval * struc , php_serialize_data_t * data ) /* {{{ */
1268
1274
{
1269
- php_var_serialize_intern (buf , struc , * data );
1275
+ php_var_serialize_intern (buf , struc , * data , false, true );
1270
1276
smart_str_0 (buf );
1271
1277
}
1272
1278
/* }}} */
0 commit comments