From d4187c784e128ed4d8ed80b03e8f239cba20d131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 31 Aug 2025 00:17:02 +0200 Subject: [PATCH 1/3] uri: Call the proper `clone_obj` handler in `uri_write_component_ex()` For external URI implementation it's possible that the `->clone_obj` handler does not match `uri_clone_obj_handler()`. Use the handler of the object instead of making assumptions. --- ext/uri/php_uri_common.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 3edda609378f3..27283775326a0 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -83,19 +83,22 @@ void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t proper static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name, zval *property_zv) { + zend_object *old_object = Z_OBJ_P(ZEND_THIS); uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); URI_ASSERT_INITIALIZATION(internal_uri); + zend_object *new_object = old_object->handlers->clone_obj(old_object); + if (new_object == NULL) { + RETURN_THROWS(); + } + const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); ZEND_ASSERT(property_handler != NULL); - zend_object *new_object = uri_clone_obj_handler(Z_OBJ_P(ZEND_THIS)); - ZEND_ASSERT(new_object != NULL); - uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); URI_ASSERT_INITIALIZATION(new_internal_uri); if (UNEXPECTED(property_handler->write_func == NULL)) { - zend_readonly_property_modification_error_ex(ZSTR_VAL(Z_OBJ_P(ZEND_THIS)->ce->name), + zend_readonly_property_modification_error_ex(ZSTR_VAL(old_object->ce->name), ZSTR_VAL(get_known_string_by_property_name(property_name))); zend_object_release(new_object); RETURN_THROWS(); @@ -110,7 +113,7 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_na } ZEND_ASSERT(Z_ISUNDEF(errors)); - RETVAL_OBJ(new_object); + RETURN_OBJ(new_object); } void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) From 7b22549cabd98c6edbf713ad085f36e396e59f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 31 Aug 2025 00:20:49 +0200 Subject: [PATCH 2/3] uri: Call `RETVAL_OBJ(new_object)` early in `uri_write_component_ex()` This allows to remove some error handling logic. --- ext/uri/php_uri_common.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 27283775326a0..6bb3f7d9946cc 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -92,6 +92,10 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_na RETURN_THROWS(); } + /* Assign the object early. The engine will take care of destruction in + * case of an exception being thrown. */ + RETVAL_OBJ(new_object); + const uri_property_handler_t *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); ZEND_ASSERT(property_handler != NULL); @@ -100,7 +104,6 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_na if (UNEXPECTED(property_handler->write_func == NULL)) { zend_readonly_property_modification_error_ex(ZSTR_VAL(old_object->ce->name), ZSTR_VAL(get_known_string_by_property_name(property_name))); - zend_object_release(new_object); RETURN_THROWS(); } @@ -108,12 +111,10 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, uri_property_na ZVAL_UNDEF(&errors); if (UNEXPECTED(property_handler->write_func(new_internal_uri, property_zv, &errors) == FAILURE)) { zval_ptr_dtor(&errors); - zend_object_release(new_object); RETURN_THROWS(); } ZEND_ASSERT(Z_ISUNDEF(errors)); - RETURN_OBJ(new_object); } void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, uri_property_name_t property_name) From ee0a7dfe3e4f9f926a7715a896212ad090447ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sun, 31 Aug 2025 00:28:58 +0200 Subject: [PATCH 3/3] uri: Remove now-useless declaration of `uri_clone_obj_handler` from php_uri_common.h --- ext/uri/php_uri.c | 2 +- ext/uri/php_uri_common.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 17278c0f422e8..ccd299fd206a8 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -979,7 +979,7 @@ static void uri_free_obj_handler(zend_object *object) zend_object_std_dtor(&uri_object->std); } -zend_object *uri_clone_obj_handler(zend_object *object) +static zend_object *uri_clone_obj_handler(zend_object *object) { uri_object_t *uri_object = uri_object_from_obj(object); uri_internal_t *internal_uri = uri_internal_from_obj(object); diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 2c461ab3fb0a4..0b2b4ddbe7973 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -27,7 +27,6 @@ extern zend_class_entry *uri_invalid_uri_exception_ce; extern zend_class_entry *uri_whatwg_invalid_url_exception_ce; extern zend_class_entry *uri_whatwg_url_validation_error_type_ce; extern zend_class_entry *uri_whatwg_url_validation_error_ce; -extern zend_object *uri_clone_obj_handler(zend_object *object); typedef enum { URI_RECOMPOSITION_RAW_ASCII,