From 4c04ff33c969f5371efb4b25a155dba50db701b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 9 Sep 2025 08:37:51 +0200 Subject: [PATCH] uri: Make the `.free_uri` handlers safe to call with `NULL` (#19627) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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`. * uri: Stop checking for `NULL` before calling `->free_uri()` This implicitly fixes an `UNEXPECTED(…->uri != NULL)` in `uri_free_obj_handler` that likely should have read `EXPECTED` instead. * uri: Remove unnecessary reset of `->uri` to `NULL` in `php_uri_object_handler_free()` * uri: Document the requirement of `free_uri()` being safe with `NULL` --- ext/uri/php_uri.c | 11 ++--------- ext/uri/php_uri_common.h | 2 +- ext/uri/uri_parser_php_parse_url.c | 4 ++++ ext/uri/uri_parser_rfc3986.c | 6 +++++- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index f9b5dadcc97..ba4af1eb366 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -830,9 +830,7 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS) } uri_internal_t *internal_uri = uri_internal_from_obj(object); - 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)); @@ -1025,12 +1023,7 @@ PHPAPI void php_uri_object_handler_free(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); zend_object_std_dtor(&uri_object->std); } diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 999dca0e53a..1db692136e1 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -122,7 +122,7 @@ typedef struct uri_parser_t { /** * Frees the provided URI. * - * @param uri The input URI + * @param uri The URI to free. Must do nothing if NULL. */ void (*free_uri)(void *uri); diff --git a/ext/uri/uri_parser_php_parse_url.c b/ext/uri/uri_parser_php_parse_url.c index 8a22f9fa4dd..1803bdb56fc 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 01f89f4ccc7..a4507a610d7 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -554,10 +554,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);