1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

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

* uri: Streamline implementation of `uriparser_parse_uri_ex()`

Avoid the use of a macro and streamline the logic.

* uri: Improve exceptions for `Uri\Rfc3986\Uri`

* uri: Allow empty URIs for RFC3986

* NEWS

* uri: Improve ext/uri/tests/004.phpt for empty URIs
This commit is contained in:
Tim Düsterhus
2025-07-18 17:38:44 +02:00
committed by GitHub
parent 063d795599
commit 5fdc02282f
4 changed files with 84 additions and 47 deletions

1
NEWS
View File

@@ -19,6 +19,7 @@ PHP NEWS
. Error handling of Uri\WhatWg\Url::withHost() is fixed when the input
contains a port. Now, it triggers an exception; previously, the error
was silently swallowed. (Máté Kocsis)
. Support empty URIs with Uri\Rfc3986\Uri. (timwolla)
17 Jul 2025, PHP 8.5.0alpha2

View File

@@ -21,7 +21,6 @@
#include "Zend/zend_exceptions.h"
static void uriparser_free_uri(void *uri);
static void throw_invalid_uri_exception(void);
static void *uriparser_malloc(UriMemoryManager *memory_manager, size_t size)
{
@@ -293,51 +292,59 @@ static uriparser_uris_t *uriparser_create_uris(void)
return uriparser_uris;
}
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();
UriUriA uri = {0};
if (uriparser_base_urls == NULL) {
PARSE_URI(&uriparser_uris->uri, uri_str, uriparser_uris, silent);
uriMakeOwnerMmA(&uriparser_uris->uri, mm);
} else {
UriUriA uri;
PARSE_URI(&uri, uri_str, uriparser_uris, silent);
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();
}
return NULL;
/* Parse the URI. */
if (uriParseSingleUriExMmA(&uri, ZSTR_VAL(uri_str), ZSTR_VAL(uri_str) + ZSTR_LEN(uri_str), NULL, mm) != URI_SUCCESS) {
if (!silent) {
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified URI is malformed", 0);
}
uriMakeOwnerMmA(&uriparser_uris->uri, mm);
uriFreeUriMembersMmA(&uri, mm);
goto fail;
}
if (uriparser_base_urls != NULL) {
UriUriA tmp = {0};
/* Combine the parsed URI with the base URI and store the result in 'tmp',
* since the target and source URLs must be distinct. */
int result = uriAddBaseUriExMmA(&tmp, &uri, &uriparser_base_urls->uri, URI_RESOLVE_STRICTLY, mm);
if (result != URI_SUCCESS) {
if (!silent) {
switch (result) {
case URI_ERROR_ADDBASE_REL_BASE:
zend_throw_exception(uri_invalid_uri_exception_ce, "The specified base URI must be absolute", 0);
break;
default:
/* This should be unreachable in practice. */
zend_throw_exception(uri_invalid_uri_exception_ce, "Failed to resolve the specified URI against the base URI", 0);
break;
}
}
goto fail;
}
/* 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);
return NULL;
}
void *uriparser_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors, bool silent)

View File

@@ -5,12 +5,7 @@ uri
--FILE--
<?php
try {
new Uri\Rfc3986\Uri("");
} catch (Uri\InvalidUriException $e) {
echo $e->getMessage() . "\n";
}
var_dump(new Uri\Rfc3986\Uri(""));
var_dump(Uri\Rfc3986\Uri::parse(""));
try {
@@ -29,8 +24,42 @@ var_dump(Uri\WhatWg\Url::parse("http://RuPaul's Drag Race All Stars 7 Winners Ca
?>
--EXPECTF--
The specified URI is malformed
NULL
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
NULL
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
NULL
["fragment"]=>
NULL
}
object(Uri\Rfc3986\Uri)#%d (%d) {
["scheme"]=>
NULL
["username"]=>
NULL
["password"]=>
NULL
["host"]=>
NULL
["port"]=>
NULL
["path"]=>
string(0) ""
["query"]=>
NULL
["fragment"]=>
NULL
}
The specified URI is malformed (MissingSchemeNonRelativeUrl)
NULL
object(Uri\Rfc3986\Uri)#%d (%d) {

View File

@@ -12,4 +12,4 @@ try {
}
?>
--EXPECT--
The specified URI is malformed
The specified base URI must be absolute