2525#include <libxml/parserInternals.h>
2626#include "zend_strtod.h"
2727#include "zend_interfaces.h"
28+ #include "zend_enum.h"
2829
2930/* zval type decode */
3031static zval * to_zval_double (zval * ret , encodeTypePtr type , xmlNodePtr data );
@@ -830,33 +831,69 @@ static zval *to_zval_hexbin(zval *ret, encodeTypePtr type, xmlNodePtr data)
830831 return ret ;
831832}
832833
834+ static zend_string * get_serialization_string_from_zval (zval * data )
835+ {
836+ switch (Z_TYPE_P (data )) {
837+ case IS_OBJECT :
838+ if (Z_OBJCE_P (data )-> ce_flags & ZEND_ACC_ENUM ) {
839+ if (UNEXPECTED (Z_OBJCE_P (data )-> enum_backing_type == IS_UNDEF )) {
840+ zend_value_error ("Non-backed enums have no default serialization" );
841+ return zend_empty_string ;
842+ } else {
843+ zval * value = zend_enum_fetch_case_value (Z_OBJ_P (data ));
844+ return zval_get_string_func (value );
845+ }
846+ }
847+ ZEND_FALLTHROUGH ;
848+ default :
849+ return zval_get_string_func (data );
850+ }
851+ }
852+
853+ static zend_long get_serialization_long_from_zval (zval * data )
854+ {
855+ switch (Z_TYPE_P (data )) {
856+ case IS_OBJECT :
857+ if (Z_OBJCE_P (data )-> ce_flags & ZEND_ACC_ENUM ) {
858+ if (UNEXPECTED (Z_OBJCE_P (data )-> enum_backing_type != IS_LONG )) {
859+ if (Z_OBJCE_P (data )-> enum_backing_type == IS_UNDEF ) {
860+ zend_value_error ("Non-backed enums have no default serialization" );
861+ } else {
862+ zend_value_error ("String-backed enum cannot be serialized as int" );
863+ }
864+ return 0 ;
865+ } else {
866+ zval * value = zend_enum_fetch_case_value (Z_OBJ_P (data ));
867+ ZEND_ASSERT (Z_TYPE_P (value ) == IS_LONG );
868+ return Z_LVAL_P (value );
869+ }
870+ }
871+ ZEND_FALLTHROUGH ;
872+ default :
873+ return zval_get_long (data );
874+ }
875+ }
876+
833877static xmlNodePtr to_xml_string (encodeTypePtr type , zval * data , int style , xmlNodePtr parent )
834878{
835879 xmlNodePtr ret , text ;
836- char * str ;
837- int new_len ;
838880
839881 ret = xmlNewNode (NULL , BAD_CAST ("BOGUS" ));
840882 xmlAddChild (parent , ret );
841883 FIND_ZVAL_NULL (data , ret , style );
842884
843- if (Z_TYPE_P (data ) == IS_STRING ) {
844- str = estrndup (Z_STRVAL_P (data ), Z_STRLEN_P (data ));
845- new_len = Z_STRLEN_P (data );
846- } else {
847- zend_string * tmp = zval_get_string_func (data );
848- str = estrndup (ZSTR_VAL (tmp ), ZSTR_LEN (tmp ));
849- new_len = ZSTR_LEN (tmp );
850- zend_string_release_ex (tmp , 0 );
851- }
885+ zend_string * serialization = get_serialization_string_from_zval (data );
886+ char * str = ZSTR_VAL (serialization );
887+ size_t new_len = ZSTR_LEN (serialization );
852888
853889 if (SOAP_GLOBAL (encoding ) != NULL ) {
854890 xmlBufferPtr in = xmlBufferCreateStatic (str , new_len );
855891 xmlBufferPtr out = xmlBufferCreate ();
856892 int n = xmlCharEncInFunc (SOAP_GLOBAL (encoding ), out , in );
857893
858894 if (n >= 0 ) {
859- efree (str );
895+ zend_string_release (serialization );
896+ serialization = NULL ;
860897 str = estrdup ((char * )xmlBufferContent (out ));
861898 new_len = n ;
862899 }
@@ -907,7 +944,11 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo
907944
908945 text = xmlNewTextLen (BAD_CAST (str ), new_len );
909946 xmlAddChild (ret , text );
910- efree (str );
947+ if (serialization ) {
948+ zend_string_release (serialization );
949+ } else {
950+ efree (str );
951+ }
911952
912953 if (style == SOAP_ENCODED ) {
913954 set_ns_and_type (ret , type );
@@ -918,19 +959,14 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo
918959static xmlNodePtr to_xml_base64 (encodeTypePtr type , zval * data , int style , xmlNodePtr parent )
919960{
920961 xmlNodePtr ret , text ;
921- zend_string * str ;
922962
923963 ret = xmlNewNode (NULL , BAD_CAST ("BOGUS" ));
924964 xmlAddChild (parent , ret );
925965 FIND_ZVAL_NULL (data , ret , style );
926966
927- if (Z_TYPE_P (data ) == IS_STRING ) {
928- str = php_base64_encode ((unsigned char * )Z_STRVAL_P (data ), Z_STRLEN_P (data ));
929- } else {
930- zend_string * tmp = zval_get_string_func (data );
931- str = php_base64_encode ((unsigned char * ) ZSTR_VAL (tmp ), ZSTR_LEN (tmp ));
932- zend_string_release_ex (tmp , 0 );
933- }
967+ zend_string * serialization = get_serialization_string_from_zval (data );
968+ zend_string * str = php_base64_encode ((unsigned char * ) ZSTR_VAL (serialization ), ZSTR_LEN (serialization ));
969+ zend_string_release (serialization );
934970
935971 text = xmlNewTextLen (BAD_CAST (ZSTR_VAL (str )), ZSTR_LEN (str ));
936972 xmlAddChild (ret , text );
@@ -955,7 +991,7 @@ static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNo
955991 FIND_ZVAL_NULL (data , ret , style );
956992
957993 if (Z_TYPE_P (data ) != IS_STRING ) {
958- ZVAL_STR (& tmp , zval_get_string_func (data ));
994+ ZVAL_STR (& tmp , get_serialization_string_from_zval (data ));
959995 data = & tmp ;
960996 }
961997 str = (unsigned char * ) safe_emalloc (Z_STRLEN_P (data ) * 2 , sizeof (char ), 1 );
@@ -1063,7 +1099,7 @@ static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNode
10631099 snprintf (s , sizeof (s ), "%0.0F" ,floor (Z_DVAL_P (data )));
10641100 xmlNodeSetContent (ret , BAD_CAST (s ));
10651101 } else {
1066- zend_string * str = zend_long_to_str (zval_get_long (data ));
1102+ zend_string * str = zend_long_to_str (get_serialization_long_from_zval (data ));
10671103 xmlNodeSetContentLen (ret , BAD_CAST (ZSTR_VAL (str )), ZSTR_LEN (str ));
10681104 zend_string_release_ex (str , 0 );
10691105 }
@@ -3026,7 +3062,7 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP
30263062 smart_str list = {0 };
30273063
30283064 if (Z_TYPE_P (data ) != IS_STRING ) {
3029- ZVAL_STR (& tmp , zval_get_string_func (data ));
3065+ ZVAL_STR (& tmp , get_serialization_string_from_zval (data ));
30303066 data = & tmp ;
30313067 }
30323068 str = estrndup (Z_STRVAL_P (data ), Z_STRLEN_P (data ));
@@ -3135,13 +3171,10 @@ static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodeP
31353171 } ZEND_HASH_FOREACH_END ();
31363172 return ret ;
31373173 }
3138- if (Z_TYPE_P (data ) == IS_STRING ) {
3139- ret = xmlNewTextLen (BAD_CAST (Z_STRVAL_P (data )), Z_STRLEN_P (data ));
3140- } else {
3141- zend_string * tmp = zval_get_string_func (data );
3142- ret = xmlNewTextLen (BAD_CAST (ZSTR_VAL (tmp )), ZSTR_LEN (tmp ));
3143- zend_string_release_ex (tmp , 0 );
3144- }
3174+
3175+ zend_string * serialization = get_serialization_string_from_zval (data );
3176+ ret = xmlNewTextLen (BAD_CAST (ZSTR_VAL (serialization )), ZSTR_LEN (serialization ));
3177+ zend_string_release_ex (serialization , false);
31453178
31463179 ret -> name = xmlStringTextNoenc ;
31473180 ret -> parent = parent ;
0 commit comments