diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 4c5a496c3eec..c9f9207bbceb 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -332,16 +332,33 @@ static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors) } ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( - INTERNAL_FUNCTION_PARAMETERS, const uri_parser_t *uri_parser, const zend_string *uri_str, const zend_object *base_url_object, + INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const zend_object *base_url_object, bool should_throw, bool should_update_this_object, zval *errors_zv ) { + + uri_object_t *uri_object; + if (should_update_this_object) { + uri_object = Z_URI_OBJECT_P(ZEND_THIS); + } else { + if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) { + object_init_ex(return_value, Z_CE_P(ZEND_THIS)); + } else { + object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS)); + } + uri_object = Z_URI_OBJECT_P(return_value); + } + + const uri_parser_t *uri_parser = uri_object->internal.parser; + zval errors; ZVAL_UNDEF(&errors); void *base_url = NULL; if (base_url_object != NULL) { + ZEND_ASSERT(base_url_object->ce == uri_object->std.ce); uri_internal_t *internal_base_url = uri_internal_from_obj(base_url_object); URI_ASSERT_INITIALIZATION(internal_base_url); + ZEND_ASSERT(internal_base_url->parser == uri_parser); base_url = internal_base_url->uri; } @@ -354,6 +371,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) { RETURN_THROWS(); } + zval_ptr_dtor(return_value); RETURN_NULL(); } } @@ -363,19 +381,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( RETURN_THROWS(); } - uri_object_t *uri_object; - if (should_update_this_object) { - uri_object = Z_URI_OBJECT_P(ZEND_THIS); - } else { - if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) { - object_init_ex(return_value, Z_CE_P(ZEND_THIS)); - } else { - object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS)); - } - uri_object = Z_URI_OBJECT_P(return_value); - } - - uri_object->internal.parser = uri_parser; uri_object->internal.uri = uri; } @@ -390,7 +395,7 @@ static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, uri_rfc3986_uri_ce) ZEND_PARSE_PARAMETERS_END(); - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &php_uri_parser_rfc3986, uri_str, base_url_object, is_constructor, is_constructor, NULL); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, base_url_object, is_constructor, is_constructor, NULL); } PHP_METHOD(Uri_Rfc3986_Uri, parse) @@ -477,7 +482,7 @@ static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) Z_PARAM_ZVAL(errors) ZEND_PARSE_PARAMETERS_END(); - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &php_uri_parser_whatwg, uri_str, base_url_object, is_constructor, is_constructor, errors); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, base_url_object, is_constructor, is_constructor, errors); } PHP_METHOD(Uri_WhatWg_Url, parse) @@ -692,11 +697,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, resolve) Z_PARAM_PATH_STR(uri_str) ZEND_PARSE_PARAMETERS_END(); - zend_object *this_object = Z_OBJ_P(ZEND_THIS); - uri_internal_t *internal_uri = uri_internal_from_obj(this_object); - URI_ASSERT_INITIALIZATION(internal_uri); - - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->parser, uri_str, this_object, true, false, NULL); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, Z_OBJ_P(ZEND_THIS), true, false, NULL); } PHP_METHOD(Uri_Rfc3986_Uri, __serialize) @@ -729,7 +730,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize) zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr); } -static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *uri_parser_name) +static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS) { HashTable *data; @@ -765,7 +766,6 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *uri_parser } uri_internal_t *internal_uri = uri_internal_from_obj(object); - internal_uri->parser = uri_parser_by_name(uri_parser_name, strlen(uri_parser_name)); if (internal_uri->uri != NULL) { internal_uri->parser->free_uri(internal_uri->uri); } @@ -791,7 +791,7 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *uri_parser PHP_METHOD(Uri_Rfc3986_Uri, __unserialize) { - uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PARSER_RFC3986); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo) @@ -905,11 +905,7 @@ PHP_METHOD(Uri_WhatWg_Url, resolve) Z_PARAM_ZVAL(errors) ZEND_PARSE_PARAMETERS_END(); - zend_object *this_object = Z_OBJ_P(ZEND_THIS); - uri_internal_t *internal_uri = uri_internal_from_obj(this_object); - URI_ASSERT_INITIALIZATION(internal_uri); - - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->parser, uri_str, this_object, true, false, errors); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, Z_OBJ_P(ZEND_THIS), true, false, errors); } PHP_METHOD(Uri_WhatWg_Url, __serialize) @@ -944,7 +940,7 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize) PHP_METHOD(Uri_WhatWg_Url, __unserialize) { - uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PARSER_WHATWG); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } PHP_METHOD(Uri_WhatWg_Url, __debugInfo) @@ -956,14 +952,29 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo) RETURN_ARR(uri_get_debug_properties(object)); } -static zend_object *uri_create_object_handler(zend_class_entry *class_type) +static uri_object_t *uri_create_object_handler(zend_class_entry *class_type, const uri_parser_t *parser) { uri_object_t *uri_object = zend_object_alloc(sizeof(*uri_object), class_type); zend_object_std_init(&uri_object->std, class_type); object_properties_init(&uri_object->std, class_type); - return &uri_object->std; + uri_object->internal = (uri_internal_t){ + .parser = parser, + .uri = NULL, + }; + + return uri_object; +} + +static zend_object *uri_create_object_handler_rfc3986(zend_class_entry *ce) +{ + return &uri_create_object_handler(ce, &php_uri_parser_rfc3986)->std; +} + +static zend_object *uri_create_object_handler_whatwg(zend_class_entry *ce) +{ + return &uri_create_object_handler(ce, &php_uri_parser_whatwg)->std; } static void uri_free_obj_handler(zend_object *object) @@ -986,11 +997,8 @@ zend_object *uri_clone_obj_handler(zend_object *object) URI_ASSERT_INITIALIZATION(internal_uri); - zend_object *new_object = uri_create_object_handler(object->ce); - ZEND_ASSERT(new_object != NULL); - uri_object_t *new_uri_object = uri_object_from_obj(new_object); - - new_uri_object->internal.parser = internal_uri->parser; + uri_object_t *new_uri_object = uri_object_from_obj(object->ce->create_object(object->ce)); + ZEND_ASSERT(new_uri_object->internal.parser == internal_uri->parser); void *uri = internal_uri->parser->clone_uri(internal_uri->uri); ZEND_ASSERT(uri != NULL); @@ -1002,16 +1010,6 @@ zend_object *uri_clone_obj_handler(zend_object *object) return &new_uri_object->std; } -ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers) -{ - ce->create_object = uri_create_object_handler; - ce->default_object_handlers = object_handlers; - memcpy(object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - object_handlers->offset = XtOffsetOf(uri_object_t, std); - object_handlers->free_obj = uri_free_obj_handler; - object_handlers->clone_obj = uri_clone_obj_handler; -} - PHPAPI zend_result php_uri_parser_register(const uri_parser_t *uri_parser) { zend_string *key = zend_string_init_interned(uri_parser->name, strlen(uri_parser->name), true); @@ -1032,10 +1030,20 @@ PHPAPI zend_result php_uri_parser_register(const uri_parser_t *uri_parser) static PHP_MINIT_FUNCTION(uri) { uri_rfc3986_uri_ce = register_class_Uri_Rfc3986_Uri(); - php_uri_implementation_set_object_handlers(uri_rfc3986_uri_ce, &uri_rfc3986_uri_object_handlers); + uri_rfc3986_uri_ce->create_object = uri_create_object_handler_rfc3986; + uri_rfc3986_uri_ce->default_object_handlers = &uri_rfc3986_uri_object_handlers; + memcpy(&uri_rfc3986_uri_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + uri_rfc3986_uri_object_handlers.offset = XtOffsetOf(uri_object_t, std); + uri_rfc3986_uri_object_handlers.free_obj = uri_free_obj_handler; + uri_rfc3986_uri_object_handlers.clone_obj = uri_clone_obj_handler; uri_whatwg_url_ce = register_class_Uri_WhatWg_Url(); - php_uri_implementation_set_object_handlers(uri_whatwg_url_ce, &uri_whatwg_uri_object_handlers); + uri_whatwg_url_ce->create_object = uri_create_object_handler_whatwg; + uri_whatwg_url_ce->default_object_handlers = &uri_whatwg_uri_object_handlers; + memcpy(&uri_whatwg_uri_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + uri_whatwg_uri_object_handlers.offset = XtOffsetOf(uri_object_t, std); + uri_whatwg_uri_object_handlers.free_obj = uri_free_obj_handler; + uri_whatwg_uri_object_handlers.clone_obj = uri_clone_obj_handler; uri_comparison_mode_ce = register_class_Uri_UriComparisonMode(); uri_exception_ce = register_class_Uri_UriException(zend_ce_exception); diff --git a/ext/uri/php_uri.h b/ext/uri/php_uri.h index 19ba97dc4f38..f570d5150ffa 100644 --- a/ext/uri/php_uri.h +++ b/ext/uri/php_uri.h @@ -205,10 +205,8 @@ ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct( ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( - INTERNAL_FUNCTION_PARAMETERS, const uri_parser_t *uri_parser, const zend_string *uri_str, const zend_object *base_url_object, + INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const zend_object *base_url_object, bool should_throw, bool should_update_this_object, zval *errors_zv ); -ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers); - #endif