Skip to content

uri: Improve exceptions for Uri\Rfc3986\Uri #19161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 18, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 34 additions & 30 deletions ext/uri/php_uriparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,47 +297,51 @@ static void throw_invalid_uri_exception(void)
{
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0);
}

#define PARSE_URI(dest_uri, uri_str, uriparser_uris, silent) \
do { \
if (ZSTR_LEN(uri_str) == 0 || \
uriParseSingleUriExMmA(dest_uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS \
) { \
efree(uriparser_uris); \
if (!silent) { \
throw_invalid_uri_exception(); \
} \
return NULL; \
} \
} while (0)

void *uriparser_parse_uri_ex(const zend_string *uri_str, const uriparser_uris_t *uriparser_base_urls, bool silent)
{
uriparser_uris_t *uriparser_uris = uriparser_create_uris();

if (uriparser_base_urls == NULL) {
PARSE_URI(&uriparser_uris->uri, uri_str, uriparser_uris, silent);
uriMakeOwnerMmA(&uriparser_uris->uri, mm);
} else {
UriUriA uri;
UriUriA uri = {0};

PARSE_URI(&uri, uri_str, uriparser_uris, silent);
/* Empty URIs are always invalid. */
if (ZSTR_LEN(uri_str) == 0) {
goto fail;
}

/* Parse the URI. */
if (uriParseSingleUriExMmA(&uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS) {
goto fail;
}

if (uriAddBaseUriExMmA(&uriparser_uris->uri, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm) != URI_SUCCESS) {
efree(uriparser_uris);
uriFreeUriMembersMmA(&uri, mm);
if (!silent) {
throw_invalid_uri_exception();
}
if (uriparser_base_urls != NULL) {
UriUriA tmp = {0};

return NULL;
/* Combine the parsed URI with the base URI and store the result in 'tmp',
* since the target and source URLs must be distinct. */
if (uriAddBaseUriExMmA(&tmp, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm) != URI_SUCCESS) {
goto fail;
}

uriMakeOwnerMmA(&uriparser_uris->uri, mm);
/* Store the combined URI back into 'uri'. */
uriFreeUriMembersMmA(&uri, mm);
uri = tmp;
}

/* Make the resulting URI independent of the 'uri_str'. */
uriMakeOwnerMmA(&uri, mm);

uriparser_uris_t *uriparser_uris = uriparser_create_uris();
uriparser_uris->uri = uri;

return uriparser_uris;

fail:

uriFreeUriMembersMmA(&uri, mm);

if (!silent) {
throw_invalid_uri_exception();
}

return NULL;
}

void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)
Expand Down