@@ -364,7 +364,7 @@ PHPAPI void php_uri_instantiate_uri(
364364 void * base_url = NULL ;
365365 if (base_url_object != NULL ) {
366366 uri_internal_t * internal_base_url = uri_internal_from_obj (base_url_object );
367- URI_CHECK_INITIALIZATION (internal_base_url );
367+ URI_ASSERT_INITIALIZATION (internal_base_url );
368368 base_url = internal_base_url -> uri ;
369369 }
370370
@@ -522,7 +522,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, getPort)
522522
523523PHP_METHOD (Uri_Rfc3986_Uri , withPort )
524524{
525- URI_WITHER_LONG (ZSTR_KNOWN (ZEND_STR_PORT ));
525+ URI_WITHER_LONG_OR_NULL (ZSTR_KNOWN (ZEND_STR_PORT ));
526526}
527527
528528PHP_METHOD (Uri_Rfc3986_Uri , getPath )
@@ -574,10 +574,10 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z
574574{
575575 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
576576 uri_internal_t * this_internal_uri = uri_internal_from_obj (this_object );
577- URI_CHECK_INITIALIZATION (this_internal_uri );
577+ URI_ASSERT_INITIALIZATION (this_internal_uri );
578578
579579 uri_internal_t * that_internal_uri = uri_internal_from_obj (that_object );
580- URI_CHECK_INITIALIZATION (that_internal_uri );
580+ URI_ASSERT_INITIALIZATION (that_internal_uri );
581581
582582 if (this_object -> ce != that_object -> ce &&
583583 !instanceof_function (this_object -> ce , that_object -> ce ) &&
@@ -595,15 +595,16 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, z
595595 }
596596
597597 zend_string * this_str = this_internal_uri -> handler -> uri_to_string (
598- this_internal_uri -> uri , URI_RECOMPOSITION_NORMALIZED_ASCII , exclude_fragment );
598+ this_internal_uri -> uri , URI_RECOMPOSITION_NORMALIZED_ASCII , exclude_fragment );
599599 if (this_str == NULL ) {
600600 zend_throw_exception_ex (NULL , 0 , "Cannot recompose %s to string" , ZSTR_VAL (this_object -> ce -> name ));
601601 RETURN_THROWS ();
602602 }
603603
604604 zend_string * that_str = that_internal_uri -> handler -> uri_to_string (
605- that_internal_uri -> uri , URI_RECOMPOSITION_NORMALIZED_ASCII , exclude_fragment );
605+ that_internal_uri -> uri , URI_RECOMPOSITION_NORMALIZED_ASCII , exclude_fragment );
606606 if (that_str == NULL ) {
607+ zend_string_release (this_str );
607608 zend_throw_exception_ex (NULL , 0 , "Cannot recompose %s to string" , ZSTR_VAL (that_object -> ce -> name ));
608609 RETURN_THROWS ();
609610 }
@@ -634,7 +635,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, toRawString)
634635
635636 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
636637 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
637- URI_CHECK_INITIALIZATION (internal_uri );
638+ URI_ASSERT_INITIALIZATION (internal_uri );
638639
639640 zend_string * uri_str = internal_uri -> handler -> uri_to_string (internal_uri -> uri , URI_RECOMPOSITION_RAW_ASCII , false);
640641 if (uri_str == NULL ) {
@@ -651,7 +652,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, toString)
651652
652653 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
653654 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
654- URI_CHECK_INITIALIZATION (internal_uri );
655+ URI_ASSERT_INITIALIZATION (internal_uri );
655656
656657 zend_string * uri_str = internal_uri -> handler -> uri_to_string (internal_uri -> uri , URI_RECOMPOSITION_NORMALIZED_ASCII , false);
657658 if (uri_str == NULL ) {
@@ -672,7 +673,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, resolve)
672673
673674 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
674675 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
675- URI_CHECK_INITIALIZATION (internal_uri );
676+ URI_ASSERT_INITIALIZATION (internal_uri );
676677
677678 php_uri_instantiate_uri (INTERNAL_FUNCTION_PARAM_PASSTHRU , internal_uri -> handler , uri_str , this_object , true, false, NULL );
678679}
@@ -683,71 +684,63 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
683684
684685 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
685686 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
686- URI_CHECK_INITIALIZATION (internal_uri );
687-
688- HashTable * result = zend_array_dup (this_object -> handlers -> get_properties (this_object ));
689- if (zend_hash_str_find_ind (result , URI_SERIALIZED_PROPERTY_NAME , sizeof (URI_SERIALIZED_PROPERTY_NAME ) - 1 ) != NULL ) {
690- zend_hash_destroy (result );
691- zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object: $__uri property is not allowed" , ZSTR_VAL (this_object -> ce -> name ));
692- RETURN_THROWS ();
693- }
687+ URI_ASSERT_INITIALIZATION (internal_uri );
694688
689+ /* Serialize state: "uri" key in the first array */
695690 zend_string * uri_str = internal_uri -> handler -> uri_to_string (internal_uri -> uri , URI_RECOMPOSITION_RAW_ASCII , false);
696691 if (uri_str == NULL ) {
697692 zend_throw_exception_ex (NULL , 0 , "Cannot recompose %s to string" , ZSTR_VAL (this_object -> ce -> name ));
698693 RETURN_THROWS ();
699694 }
695+ zval tmp ;
696+ ZVAL_STR (& tmp , uri_str );
700697
701- zval uri_zv ;
702- ZVAL_STR (& uri_zv , uri_str );
703- zend_hash_str_add_new (result , URI_SERIALIZED_PROPERTY_NAME , sizeof (URI_SERIALIZED_PROPERTY_NAME ) - 1 , & uri_zv );
704-
705- ZVAL_ARR (return_value , result );
706- }
707-
708- static void uri_restore_custom_properties (zend_object * object , uri_internal_t * internal_uri , HashTable * ht )
709- {
710- zend_string * prop_name ;
711- zval * prop_val ;
698+ array_init (return_value );
712699
713- ZEND_HASH_FOREACH_STR_KEY_VAL (ht , prop_name , prop_val ) {
714- if (!prop_name || Z_TYPE_P (prop_val ) == IS_REFERENCE ||
715- zend_string_equals_literal (prop_name , URI_SERIALIZED_PROPERTY_NAME )
716- ) {
717- continue ;
718- }
700+ zval arr ;
701+ array_init (& arr );
702+ zend_hash_str_add_new (Z_ARRVAL (arr ), URI_SERIALIZED_PROPERTY_NAME , sizeof (URI_SERIALIZED_PROPERTY_NAME ) - 1 , & tmp );
703+ zend_hash_next_index_insert (Z_ARRVAL_P (return_value ), & arr );
719704
720- zend_update_property_ex (object -> ce , object , prop_name , prop_val );
721- if (UNEXPECTED (EG (exception ) != NULL )) {
722- break ;
723- }
724- } ZEND_HASH_FOREACH_END ();
705+ /* Serialize regular properties: second array */
706+ ZVAL_ARR (& arr , this_object -> handlers -> get_properties (this_object ));
707+ Z_TRY_ADDREF (arr );
708+ zend_hash_next_index_insert (Z_ARRVAL_P (return_value ), & arr );
725709}
726710
727711static void uri_unserialize (INTERNAL_FUNCTION_PARAMETERS , const char * handler_name )
728712{
729- HashTable * properties ;
713+ HashTable * data ;
730714
731715 ZEND_PARSE_PARAMETERS_START (1 , 1 )
732- Z_PARAM_ARRAY_HT (properties )
716+ Z_PARAM_ARRAY_HT (data )
733717 ZEND_PARSE_PARAMETERS_END ();
734718
735719 zend_object * object = Z_OBJ_P (ZEND_THIS );
736- uri_internal_t * internal_uri = uri_internal_from_obj (object );
737720
738- zval * uri_zv = zend_hash_str_find_ind (properties , URI_SERIALIZED_PROPERTY_NAME , sizeof (URI_SERIALIZED_PROPERTY_NAME ) - 1 );
739- if (uri_zv == NULL ) {
740- zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object: missing \"__uri\" field" , ZSTR_VAL (object -> ce -> name ));
721+ /* Verify the expected number of elements, this implicitly ensures that no additional elements are present. */
722+ if (zend_hash_num_elements (data ) != 2 ) {
723+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (object -> ce -> name ));
724+ RETURN_THROWS ();
725+ }
726+
727+ /* Unserialize state: "uri" key in the first array */
728+ zval * arr = zend_hash_index_find (data , 0 );
729+ if (arr == NULL || Z_TYPE_P (arr ) != IS_ARRAY ) {
730+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (object -> ce -> name ));
741731 RETURN_THROWS ();
742732 }
743- if (Z_TYPE_P (uri_zv ) != IS_STRING ) {
744- zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object: \"__uri\" field is not a string" , ZSTR_VAL (object -> ce -> name ));
733+
734+ zval * uri_zv = zend_hash_str_find_ind (Z_ARRVAL_P (arr ), URI_SERIALIZED_PROPERTY_NAME , sizeof (URI_SERIALIZED_PROPERTY_NAME ) - 1 );
735+ if (uri_zv == NULL || Z_TYPE_P (uri_zv ) != IS_STRING ) {
736+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (object -> ce -> name ));
745737 RETURN_THROWS ();
746738 }
747739
748740 zval errors ;
749741 ZVAL_UNDEF (& errors );
750742
743+ uri_internal_t * internal_uri = uri_internal_from_obj (object );
751744 internal_uri -> handler = uri_handler_by_name (handler_name , strlen (handler_name ));
752745 if (internal_uri -> uri != NULL ) {
753746 internal_uri -> handler -> free_uri (internal_uri -> uri );
@@ -756,12 +749,22 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *handler_na
756749 if (internal_uri -> uri == NULL ) {
757750 throw_invalid_uri_exception (internal_uri -> handler , & errors );
758751 zval_ptr_dtor (& errors );
759- zval_ptr_dtor (uri_zv );
760752 RETURN_THROWS ();
761753 }
762754 zval_ptr_dtor (& errors );
763755
764- uri_restore_custom_properties (object , internal_uri , properties );
756+ /* Unserialize regular properties: second array */
757+ arr = zend_hash_index_find (data , 1 );
758+ if (arr == NULL || Z_TYPE_P (arr ) != IS_ARRAY ) {
759+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (object -> ce -> name ));
760+ RETURN_THROWS ();
761+ }
762+
763+ object_properties_load (object , Z_ARRVAL_P (arr ));
764+ if (EG (exception )) {
765+ zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (object -> ce -> name ));
766+ RETURN_THROWS ();
767+ }
765768}
766769
767770PHP_METHOD (Uri_Rfc3986_Uri , __unserialize )
@@ -822,7 +825,7 @@ PHP_METHOD(Uri_WhatWg_Url, withHost)
822825 ZVAL_STR_COPY (& zv , value );
823826 }
824827
825- URI_WITHER_COMMON (ZSTR_KNOWN (ZEND_STR_HOST ), & zv , return_value ) \
828+ URI_WITHER_COMMON (ZSTR_KNOWN (ZEND_STR_HOST ), & zv , return_value );
826829}
827830
828831PHP_METHOD (Uri_WhatWg_Url , equals )
@@ -845,7 +848,7 @@ PHP_METHOD(Uri_WhatWg_Url, toUnicodeString)
845848
846849 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
847850 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
848- URI_CHECK_INITIALIZATION (internal_uri );
851+ URI_ASSERT_INITIALIZATION (internal_uri );
849852
850853 RETURN_STR (internal_uri -> handler -> uri_to_string (internal_uri -> uri , URI_RECOMPOSITION_RAW_UNICODE , false));
851854}
@@ -856,7 +859,7 @@ PHP_METHOD(Uri_WhatWg_Url, toAsciiString)
856859
857860 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
858861 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
859- URI_CHECK_INITIALIZATION (internal_uri );
862+ URI_ASSERT_INITIALIZATION (internal_uri );
860863
861864 RETURN_STR (internal_uri -> handler -> uri_to_string (internal_uri -> uri , URI_RECOMPOSITION_RAW_ASCII , false));
862865}
@@ -874,7 +877,7 @@ PHP_METHOD(Uri_WhatWg_Url, resolve)
874877
875878 zend_object * this_object = Z_OBJ_P (ZEND_THIS );
876879 uri_internal_t * internal_uri = uri_internal_from_obj (this_object );
877- URI_CHECK_INITIALIZATION (internal_uri );
880+ URI_ASSERT_INITIALIZATION (internal_uri );
878881
879882 php_uri_instantiate_uri (INTERNAL_FUNCTION_PARAM_PASSTHRU , internal_uri -> handler , uri_str , this_object , true, false, errors );
880883}
@@ -920,7 +923,7 @@ static zend_object *uri_clone_obj_handler(zend_object *object)
920923 ZEND_ASSERT (new_object != NULL );
921924 uri_object_t * new_uri_object = uri_object_from_obj (new_object );
922925
923- URI_CHECK_INITIALIZATION (internal_uri );
926+ URI_ASSERT_INITIALIZATION (internal_uri );
924927
925928 new_uri_object -> internal .handler = internal_uri -> handler ;
926929
0 commit comments