From f18aacba9dd10959b61e2e43c453a381f2f49842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 00:34:09 +0200 Subject: [PATCH 1/2] uri: Make the `.free_uri` handlers safe to call with `NULL` The `php_uri_free()` function already unconditionally called `->free_uri()` and thus couldn't be safely used when the `->uri` was `NULL` for some reason. The lexbor implementation was already safe, because `lxb_url_destroy()` is guaranteed to be a noop for `NULL`. --- ext/uri/uri_parser_php_parse_url.c | 4 ++++ ext/uri/uri_parser_rfc3986.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ext/uri/uri_parser_php_parse_url.c b/ext/uri/uri_parser_php_parse_url.c index 8a22f9fa4dd04..1803bdb56fca7 100644 --- a/ext/uri/uri_parser_php_parse_url.c +++ b/ext/uri/uri_parser_php_parse_url.c @@ -158,6 +158,10 @@ static void uri_parser_php_parse_url_free(void *uri) { php_url *parse_url_uri = uri; + if (UNEXPECTED(parse_url_uri == NULL)) { + return; + } + php_url_free(parse_url_uri); } diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c index cf7235b071b4c..b52031fc23b1b 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -384,10 +384,14 @@ ZEND_ATTRIBUTE_NONNULL static zend_string *php_uri_parser_rfc3986_to_string(void return uri_string; } -ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_rfc3986_free(void *uri) +static void php_uri_parser_rfc3986_free(void *uri) { php_uri_parser_rfc3986_uris *uriparser_uris = uri; + if (UNEXPECTED(uriparser_uris == NULL)) { + return; + } + uriFreeUriMembersMmA(&uriparser_uris->uri, mm); uriFreeUriMembersMmA(&uriparser_uris->normalized_uri, mm); From 7f951c665dabbff51569f6d85bad6ef49de863a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 29 Aug 2025 00:35:27 +0200 Subject: [PATCH 2/2] uri: Stop checking for `NULL` before calling `->free_uri()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implicitly fixes an `UNEXPECTED(…->uri != NULL)` in `uri_free_obj_handler` that likely should have read `EXPECTED` instead. --- ext/uri/php_uri.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 4c5a496c3eec2..1c7ab3b15cf17 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -766,9 +766,7 @@ 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); - } + internal_uri->parser->free_uri(internal_uri->uri); internal_uri->uri = internal_uri->parser->parse_uri(Z_STRVAL_P(uri_zv), Z_STRLEN_P(uri_zv), NULL, NULL, true); if (internal_uri->uri == NULL) { zend_throw_exception_ex(NULL, 0, "Invalid serialization data for %s object", ZSTR_VAL(object->ce->name)); @@ -970,11 +968,8 @@ static void uri_free_obj_handler(zend_object *object) { uri_object_t *uri_object = uri_object_from_obj(object); - if (UNEXPECTED(uri_object->internal.uri != NULL)) { - uri_object->internal.parser->free_uri(uri_object->internal.uri); - uri_object->internal.parser = NULL; - uri_object->internal.uri = NULL; - } + uri_object->internal.parser->free_uri(uri_object->internal.uri); + uri_object->internal.uri = NULL; zend_object_std_dtor(&uri_object->std); }