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:
1
NEWS
1
NEWS
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -12,4 +12,4 @@ try {
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
The specified URI is malformed
|
||||
The specified base URI must be absolute
|
||||
|
||||
Reference in New Issue
Block a user