@@ -764,112 +764,140 @@ static int php_var_serialize_call_magic_serialize(zval *retval, zval *obj) /* {{
764
764
}
765
765
/* }}} */
766
766
767
- static void php_var_serialize_collect_names (HashTable * ht , HashTable * src ) /* {{{ */
767
+ static int php_var_serialize_try_add_sleep_prop (
768
+ HashTable * ht , HashTable * props , zend_string * name , zend_string * error_name ) /* {{{ */
768
769
{
769
- zval * val ;
770
- zend_string * name , * tmp_name ;
770
+ zval * val = zend_hash_find (props , name );
771
+ if (val == NULL ) {
772
+ return FAILURE ;
773
+ }
771
774
772
- zend_hash_init (ht , zend_hash_num_elements (src ), NULL , NULL , 0 );
773
- ZEND_HASH_FOREACH_VAL (src , val ) {
774
- if (Z_TYPE_P (val ) != IS_STRING ) {
775
- php_error_docref (NULL , E_NOTICE ,
776
- "__sleep should return an array only containing the names of instance-variables to serialize." );
775
+ if (Z_TYPE_P (val ) == IS_INDIRECT ) {
776
+ val = Z_INDIRECT_P (val );
777
+ if (Z_TYPE_P (val ) == IS_UNDEF ) {
778
+ return FAILURE ;
777
779
}
780
+ }
778
781
779
- name = zval_get_tmp_string (val , & tmp_name );
780
- if (zend_hash_exists (ht , name )) {
781
- php_error_docref (NULL , E_NOTICE ,
782
- "\"%s\" is returned from __sleep multiple times" , ZSTR_VAL (name ));
783
- zend_tmp_string_release (tmp_name );
784
- continue ;
785
- }
786
- zend_hash_add_empty_element (ht , name );
787
- zend_tmp_string_release (tmp_name );
788
- } ZEND_HASH_FOREACH_END ();
782
+ if (!zend_hash_add (ht , name , val )) {
783
+ php_error_docref (NULL , E_NOTICE ,
784
+ "\"%s\" is returned from __sleep multiple times" , ZSTR_VAL (error_name ));
785
+ return SUCCESS ;
786
+ }
787
+
788
+ Z_TRY_ADDREF_P (val );
789
+ return SUCCESS ;
789
790
}
790
791
/* }}} */
791
792
792
- static void php_var_serialize_class (smart_str * buf , zval * struc , zval * retval_ptr , php_serialize_data_t var_hash ) /* {{{ */
793
+ static void php_var_serialize_get_sleep_props (
794
+ HashTable * ht , zval * struc , HashTable * sleep_retval ) /* {{{ */
793
795
{
794
796
zend_class_entry * ce = Z_OBJCE_P (struc );
795
- HashTable names , * propers ;
796
- zval nval ;
797
- zend_string * name ;
798
-
799
- php_var_serialize_class_name (buf , struc );
800
- php_var_serialize_collect_names (& names , HASH_OF (retval_ptr ));
801
-
802
- smart_str_append_unsigned (buf , zend_hash_num_elements (& names ));
803
- smart_str_appendl (buf , ":{" , 2 );
804
-
805
- ZVAL_NULL (& nval );
806
- propers = zend_get_properties_for (struc , ZEND_PROP_PURPOSE_SERIALIZE );
797
+ HashTable * props = zend_get_properties_for (struc , ZEND_PROP_PURPOSE_SERIALIZE );
798
+ zval * name_val ;
807
799
808
- ZEND_HASH_FOREACH_STR_KEY (& names , name ) {
809
- zend_string * prot_name , * priv_name ;
800
+ zend_hash_init (ht , zend_hash_num_elements (sleep_retval ), NULL , ZVAL_PTR_DTOR , 0 );
801
+ ZEND_HASH_FOREACH_VAL (sleep_retval , name_val ) {
802
+ zend_string * name , * tmp_name , * priv_name , * prot_name ;
810
803
811
- zval * val = zend_hash_find_ex (propers , name , 1 );
812
- if (val != NULL ) {
813
- if (Z_TYPE_P (val ) == IS_INDIRECT ) {
814
- val = Z_INDIRECT_P (val );
815
- if (Z_TYPE_P (val ) == IS_UNDEF ) {
816
- goto undef_prop ;
817
- }
818
- }
804
+ ZVAL_DEREF (name_val );
805
+ if (Z_TYPE_P (name_val ) != IS_STRING ) {
806
+ php_error_docref (NULL , E_NOTICE ,
807
+ "__sleep should return an array only containing the names of instance-variables to serialize." );
808
+ }
819
809
820
- php_var_serialize_string (buf , ZSTR_VAL (name ), ZSTR_LEN (name ));
821
- php_var_serialize_intern (buf , val , var_hash );
810
+ name = zval_get_tmp_string (name_val , & tmp_name );
811
+ if (php_var_serialize_try_add_sleep_prop (ht , props , name , name ) == SUCCESS ) {
812
+ zend_tmp_string_release (tmp_name );
822
813
continue ;
823
814
}
824
815
825
816
priv_name = zend_mangle_property_name (
826
- ZSTR_VAL (ce -> name ), ZSTR_LEN (ce -> name ), ZSTR_VAL (name ), ZSTR_LEN (name ), 0 );
827
- val = zend_hash_find (propers , priv_name );
828
- if (val != NULL ) {
829
- if (Z_TYPE_P (val ) == IS_INDIRECT ) {
830
- val = Z_INDIRECT_P (val );
831
- if (Z_ISUNDEF_P (val )) {
832
- zend_string_free (priv_name );
833
- goto undef_prop ;
834
- }
835
- }
836
-
837
- php_var_serialize_string (buf , ZSTR_VAL (priv_name ), ZSTR_LEN (priv_name ));
838
- zend_string_free (priv_name );
839
- php_var_serialize_intern (buf , val , var_hash );
817
+ ZSTR_VAL (ce -> name ), ZSTR_LEN (ce -> name ),
818
+ ZSTR_VAL (name ), ZSTR_LEN (name ), ce -> type & ZEND_INTERNAL_CLASS );
819
+ if (php_var_serialize_try_add_sleep_prop (ht , props , priv_name , name ) == SUCCESS ) {
820
+ zend_tmp_string_release (tmp_name );
821
+ zend_string_release (priv_name );
840
822
continue ;
841
823
}
842
- zend_string_free (priv_name );
824
+ zend_string_release (priv_name );
843
825
844
826
prot_name = zend_mangle_property_name (
845
- "*" , 1 , ZSTR_VAL (name ), ZSTR_LEN (name ), 0 );
846
- val = zend_hash_find (propers , prot_name );
847
- if (val != NULL ) {
848
- if (Z_TYPE_P (val ) == IS_INDIRECT ) {
849
- val = Z_INDIRECT_P (val );
850
- if (Z_TYPE_P (val ) == IS_UNDEF ) {
851
- zend_string_free (prot_name );
852
- goto undef_prop ;
853
- }
854
- }
855
-
856
- php_var_serialize_string (buf , ZSTR_VAL (prot_name ), ZSTR_LEN (prot_name ));
857
- zend_string_free (prot_name );
858
- php_var_serialize_intern (buf , val , var_hash );
827
+ "*" , 1 , ZSTR_VAL (name ), ZSTR_LEN (name ), ce -> type & ZEND_INTERNAL_CLASS );
828
+ if (php_var_serialize_try_add_sleep_prop (ht , props , prot_name , name ) == SUCCESS ) {
829
+ zend_tmp_string_release (tmp_name );
830
+ zend_string_release (prot_name );
859
831
continue ;
860
832
}
861
- zend_string_free (prot_name );
833
+ zend_string_release (prot_name );
862
834
863
- undef_prop :
864
- php_var_serialize_string (buf , ZSTR_VAL (name ), ZSTR_LEN (name ));
865
- php_var_serialize_intern (buf , & nval , var_hash );
866
835
php_error_docref (NULL , E_NOTICE ,
867
- "\"%s\" returned as member variable from __sleep() but does not exist" , ZSTR_VAL (name ));
836
+ "\"%s\" returned as member variable from __sleep() but does not exist" , ZSTR_VAL (name ));
837
+ zend_hash_add (ht , name , & EG (uninitialized_zval ));
838
+ zend_tmp_string_release (tmp_name );
868
839
} ZEND_HASH_FOREACH_END ();
840
+ zend_release_properties (props );
841
+ }
842
+ /* }}} */
843
+
844
+ static void php_var_serialize_nested_data (smart_str * buf , zval * struc , HashTable * ht , uint32_t count , zend_bool incomplete_class , php_serialize_data_t var_hash ) /* {{{ */
845
+ {
846
+ smart_str_append_unsigned (buf , count );
847
+ smart_str_appendl (buf , ":{" , 2 );
848
+ if (count > 0 ) {
849
+ zend_string * key ;
850
+ zval * data ;
851
+ zend_ulong index ;
852
+
853
+ ZEND_HASH_FOREACH_KEY_VAL_IND (ht , index , key , data ) {
854
+ if (incomplete_class && strcmp (ZSTR_VAL (key ), MAGIC_MEMBER ) == 0 ) {
855
+ continue ;
856
+ }
857
+
858
+ if (!key ) {
859
+ php_var_serialize_long (buf , index );
860
+ } else {
861
+ php_var_serialize_string (buf , ZSTR_VAL (key ), ZSTR_LEN (key ));
862
+ }
863
+
864
+ if (Z_ISREF_P (data ) && Z_REFCOUNT_P (data ) == 1 ) {
865
+ data = Z_REFVAL_P (data );
866
+ }
867
+
868
+ /* we should still add element even if it's not OK,
869
+ * since we already wrote the length of the array before */
870
+ if (Z_TYPE_P (data ) == IS_ARRAY ) {
871
+ if (UNEXPECTED (Z_IS_RECURSIVE_P (data ))
872
+ || UNEXPECTED (Z_TYPE_P (struc ) == IS_ARRAY && Z_ARR_P (data ) == Z_ARR_P (struc ))) {
873
+ php_add_var_hash (var_hash , struc );
874
+ smart_str_appendl (buf , "N;" , 2 );
875
+ } else {
876
+ if (Z_REFCOUNTED_P (data )) {
877
+ Z_PROTECT_RECURSION_P (data );
878
+ }
879
+ php_var_serialize_intern (buf , data , var_hash );
880
+ if (Z_REFCOUNTED_P (data )) {
881
+ Z_UNPROTECT_RECURSION_P (data );
882
+ }
883
+ }
884
+ } else {
885
+ php_var_serialize_intern (buf , data , var_hash );
886
+ }
887
+ } ZEND_HASH_FOREACH_END ();
888
+ }
869
889
smart_str_appendc (buf , '}' );
890
+ }
891
+ /* }}} */
870
892
871
- zend_hash_destroy (& names );
872
- zend_release_properties (propers );
893
+ static void php_var_serialize_class (smart_str * buf , zval * struc , zval * retval_ptr , php_serialize_data_t var_hash ) /* {{{ */
894
+ {
895
+ HashTable props ;
896
+ php_var_serialize_get_sleep_props (& props , struc , HASH_OF (retval_ptr ));
897
+ php_var_serialize_class_name (buf , struc );
898
+ php_var_serialize_nested_data (
899
+ buf , struc , & props , zend_hash_num_elements (& props ), /* incomplete_class */ 0 , var_hash );
900
+ zend_hash_destroy (& props );
873
901
}
874
902
/* }}} */
875
903
@@ -933,6 +961,8 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
933
961
934
962
case IS_OBJECT : {
935
963
zend_class_entry * ce = Z_OBJCE_P (struc );
964
+ zend_bool incomplete_class ;
965
+ uint32_t count ;
936
966
937
967
if (zend_hash_str_exists (& ce -> function_table , "__serialize" , sizeof ("__serialize" )- 1 )) {
938
968
zval retval , obj ;
@@ -1023,75 +1053,24 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
1023
1053
return ;
1024
1054
}
1025
1055
1026
- /* fall-through */
1027
- }
1028
- case IS_ARRAY : {
1029
- uint32_t i ;
1030
- zend_bool incomplete_class = 0 ;
1031
- if (Z_TYPE_P (struc ) == IS_ARRAY ) {
1032
- smart_str_appendl (buf , "a:" , 2 );
1033
- myht = Z_ARRVAL_P (struc );
1034
- i = zend_array_count (myht );
1035
- } else {
1036
1056
incomplete_class = php_var_serialize_class_name (buf , struc );
1037
1057
myht = zend_get_properties_for (struc , ZEND_PROP_PURPOSE_SERIALIZE );
1038
1058
/* count after serializing name, since php_var_serialize_class_name
1039
1059
* changes the count if the variable is incomplete class */
1040
- i = zend_array_count (myht );
1041
- if (i > 0 && incomplete_class ) {
1042
- -- i ;
1060
+ count = zend_array_count (myht );
1061
+ if (count > 0 && incomplete_class ) {
1062
+ -- count ;
1043
1063
}
1044
- }
1045
- smart_str_append_unsigned (buf , i );
1046
- smart_str_appendl (buf , ":{" , 2 );
1047
- if (i > 0 ) {
1048
- zend_string * key ;
1049
- zval * data ;
1050
- zend_ulong index ;
1051
-
1052
- ZEND_HASH_FOREACH_KEY_VAL_IND (myht , index , key , data ) {
1053
-
1054
- if (incomplete_class && strcmp (ZSTR_VAL (key ), MAGIC_MEMBER ) == 0 ) {
1055
- continue ;
1056
- }
1057
-
1058
- if (!key ) {
1059
- php_var_serialize_long (buf , index );
1060
- } else {
1061
- php_var_serialize_string (buf , ZSTR_VAL (key ), ZSTR_LEN (key ));
1062
- }
1063
-
1064
- if (Z_ISREF_P (data ) && Z_REFCOUNT_P (data ) == 1 ) {
1065
- data = Z_REFVAL_P (data );
1066
- }
1067
-
1068
- /* we should still add element even if it's not OK,
1069
- * since we already wrote the length of the array before */
1070
- if (Z_TYPE_P (data ) == IS_ARRAY ) {
1071
- if (UNEXPECTED (Z_IS_RECURSIVE_P (data ))
1072
- || UNEXPECTED (Z_TYPE_P (struc ) == IS_ARRAY && Z_ARR_P (data ) == Z_ARR_P (struc ))) {
1073
- php_add_var_hash (var_hash , struc );
1074
- smart_str_appendl (buf , "N;" , 2 );
1075
- } else {
1076
- if (Z_REFCOUNTED_P (data )) {
1077
- Z_PROTECT_RECURSION_P (data );
1078
- }
1079
- php_var_serialize_intern (buf , data , var_hash );
1080
- if (Z_REFCOUNTED_P (data )) {
1081
- Z_UNPROTECT_RECURSION_P (data );
1082
- }
1083
- }
1084
- } else {
1085
- php_var_serialize_intern (buf , data , var_hash );
1086
- }
1087
- } ZEND_HASH_FOREACH_END ();
1088
- }
1089
- smart_str_appendc (buf , '}' );
1090
- if (Z_TYPE_P (struc ) == IS_OBJECT ) {
1064
+ php_var_serialize_nested_data (buf , struc , myht , count , incomplete_class , var_hash );
1091
1065
zend_release_properties (myht );
1066
+ return ;
1092
1067
}
1068
+ case IS_ARRAY :
1069
+ smart_str_appendl (buf , "a:" , 2 );
1070
+ myht = Z_ARRVAL_P (struc );
1071
+ php_var_serialize_nested_data (
1072
+ buf , struc , myht , zend_array_count (myht ), /* incomplete_class */ 0 , var_hash );
1093
1073
return ;
1094
- }
1095
1074
case IS_REFERENCE :
1096
1075
struc = Z_REFVAL_P (struc );
1097
1076
goto again ;
0 commit comments