From d158e32fded991c5b23fd1493e62746436ddc70c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 11 Sep 2025 22:16:39 +0200 Subject: [PATCH 1/3] uri: Do not check the return value of `uri_property_handler_from_internal_uri()` It's impossible for this function to return `NULL`, since it will always return a positive offset into a struct. --- ext/uri/php_uri.c | 3 --- ext/uri/php_uri_common.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 1af634d643b1f..4763cd6d5d1aa 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -127,9 +127,6 @@ ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const php_uri_parser ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_get_property(const uri_internal_t *internal_uri, php_uri_property_name property_name, php_uri_component_read_mode read_mode, zval *zv) { const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - if (property_handler == NULL) { - return FAILURE; - } return property_handler->read(internal_uri->uri, read_mode, zv); } diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 57472ad2640b8..ab9533959161b 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -73,7 +73,6 @@ void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name prop URI_ASSERT_INITIALIZATION(internal_uri); const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - ZEND_ASSERT(property_handler != NULL); if (UNEXPECTED(property_handler->read(internal_uri->uri, component_read_mode, return_value) == FAILURE)) { zend_throw_error(NULL, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name))); @@ -97,7 +96,6 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, php_uri_propert RETVAL_OBJ(new_object); const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - ZEND_ASSERT(property_handler != NULL); uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); URI_ASSERT_INITIALIZATION(new_internal_uri); From dbd71867917801131c1acc584441af6b3fb7c7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 11 Sep 2025 22:07:37 +0200 Subject: [PATCH 2/3] uri: Optimize `php_uri_get_*()` Currently the `php_uri_get_*()` functions call into `php_uri_get_property()` with a constant `php_uri_property_name`. This name will then be used to look up the correct property handler by a function in a different compilation unit. Improve this by making `uri_property_handler_from_internal_uri` take a `php_uri_parser` rather than a `uri_internal_t`, defining it in a header as inlinable (and renaming it to better match its updated purpose). This allows the compiler to fully inline `php_uri_get_property()`, such that no dynamic lookups will need to happen. --- ext/uri/php_uri.c | 4 ++-- ext/uri/php_uri_common.c | 27 ++------------------------- ext/uri/php_uri_common.h | 24 +++++++++++++++++++++++- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 4763cd6d5d1aa..d419ed37be27b 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -124,9 +124,9 @@ ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const php_uri_parser return internal_uri; } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_get_property(const uri_internal_t *internal_uri, php_uri_property_name property_name, php_uri_component_read_mode read_mode, zval *zv) +ZEND_ATTRIBUTE_NONNULL static inline zend_result php_uri_get_property(const uri_internal_t *internal_uri, php_uri_property_name property_name, php_uri_component_read_mode read_mode, zval *zv) { - const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); return property_handler->read(internal_uri->uri, read_mode, zv); } diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index ab9533959161b..efb7688a94502 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -19,29 +19,6 @@ #include "Zend/zend_exceptions.h" #include "php_uri_common.h" -const php_uri_property_handler *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, php_uri_property_name property_name) -{ - switch (property_name) { - case PHP_URI_PROPERTY_NAME_SCHEME: - return &internal_uri->parser->property_handler.scheme; - case PHP_URI_PROPERTY_NAME_USERNAME: - return &internal_uri->parser->property_handler.username; - case PHP_URI_PROPERTY_NAME_PASSWORD: - return &internal_uri->parser->property_handler.password; - case PHP_URI_PROPERTY_NAME_HOST: - return &internal_uri->parser->property_handler.host; - case PHP_URI_PROPERTY_NAME_PORT: - return &internal_uri->parser->property_handler.port; - case PHP_URI_PROPERTY_NAME_PATH: - return &internal_uri->parser->property_handler.path; - case PHP_URI_PROPERTY_NAME_QUERY: - return &internal_uri->parser->property_handler.query; - case PHP_URI_PROPERTY_NAME_FRAGMENT: - return &internal_uri->parser->property_handler.fragment; - EMPTY_SWITCH_DEFAULT_CASE() - } -} - static zend_string *get_known_string_by_property_name(php_uri_property_name property_name) { switch (property_name) { @@ -72,7 +49,7 @@ void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name prop uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); URI_ASSERT_INITIALIZATION(internal_uri); - const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); if (UNEXPECTED(property_handler->read(internal_uri->uri, component_read_mode, return_value) == FAILURE)) { zend_throw_error(NULL, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name))); @@ -95,7 +72,7 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, php_uri_propert * case of an exception being thrown. */ RETVAL_OBJ(new_object); - const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); URI_ASSERT_INITIALIZATION(new_internal_uri); diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index c56603f9a50e1..f061db6f981b1 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -166,7 +166,29 @@ PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object); #define PHP_URI_PARSER_PHP_PARSE_URL "parse_url" #define URI_SERIALIZED_PROPERTY_NAME "uri" -const php_uri_property_handler *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, php_uri_property_name property_name); +static inline const php_uri_property_handler *php_uri_parser_property_handler_by_name(const php_uri_parser *parser, php_uri_property_name property_name) +{ + switch (property_name) { + case PHP_URI_PROPERTY_NAME_SCHEME: + return &parser->property_handler.scheme; + case PHP_URI_PROPERTY_NAME_USERNAME: + return &parser->property_handler.username; + case PHP_URI_PROPERTY_NAME_PASSWORD: + return &parser->property_handler.password; + case PHP_URI_PROPERTY_NAME_HOST: + return &parser->property_handler.host; + case PHP_URI_PROPERTY_NAME_PORT: + return &parser->property_handler.port; + case PHP_URI_PROPERTY_NAME_PATH: + return &parser->property_handler.path; + case PHP_URI_PROPERTY_NAME_QUERY: + return &parser->property_handler.query; + case PHP_URI_PROPERTY_NAME_FRAGMENT: + return &parser->property_handler.fragment; + EMPTY_SWITCH_DEFAULT_CASE() + } +} + void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode); void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); From fcb568f22a7fdabf4e6cbc62d59647554a62e788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 11 Sep 2025 22:21:02 +0200 Subject: [PATCH 3/3] uri: Eliminate `php_uri_get_property()` entirely Spelling out the effective implementation explicitly is not much longer than going through `php_uri_get_property()`, but much more explicit in what is happening. --- ext/uri/php_uri.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index d419ed37be27b..a09a93dbc0365 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -124,51 +124,44 @@ ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const php_uri_parser return internal_uri; } -ZEND_ATTRIBUTE_NONNULL static inline zend_result php_uri_get_property(const uri_internal_t *internal_uri, php_uri_property_name property_name, php_uri_component_read_mode read_mode, zval *zv) -{ - const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); - - return property_handler->read(internal_uri->uri, read_mode, zv); -} - ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_SCHEME, read_mode, zv); + return internal_uri->parser->property_handler.scheme.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_USERNAME, read_mode, zv); + return internal_uri->parser->property_handler.username.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_PASSWORD, read_mode, zv); + return internal_uri->parser->property_handler.password.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_HOST, read_mode, zv); + return internal_uri->parser->property_handler.host.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_PORT, read_mode, zv); + return internal_uri->parser->property_handler.port.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_PATH, read_mode, zv); + return internal_uri->parser->property_handler.path.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_QUERY, read_mode, zv); + return internal_uri->parser->property_handler.query.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_FRAGMENT, read_mode, zv); + return internal_uri->parser->property_handler.fragment.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(uri_internal_t *internal_uri)