mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
uri: Fix handling of the errors == NULL && !silent for uri_parser_whatwg (#19748)
* uri: Fix handling of the `errors == NULL && !silent` for uri_parser_whatwg Previously, when `errors` was `NULL`, the `errors` pointer was used to set the `$errors` property when throwing the exception, leading to a crash. Use a local zval to pass the errors to the Exception and copy it into the `errors` input when it is non-`NULL`. * uri: Only pass the `errors` zval when interested in it in `php_uri_instantiate_uri()` This is no longer necessary since the previous commit and also is a layering violation, since `php_uri_instantiate_uri()` should not care how `parse_uri()` works internally. * uri: Use `ZVAL_EMPTY_ARRAY()` when no parsing errors are available * uri: Avoid redundant refcounting in error handling of uri_parser_whatwg * NEWS
This commit is contained in:
2
NEWS
2
NEWS
@@ -87,6 +87,8 @@ PHP NEWS
|
||||
(timwolla)
|
||||
. Return null instead of 0 for Uri\Rfc3986\Uri::getPort() when the
|
||||
URI contains an empty port. (timwolla)
|
||||
. Fixed creation of the InvalidUrlException when not passing an
|
||||
errors zval to the internal whatwg parser. (timwolla)
|
||||
. Clean up naming of internal API. (timwolla)
|
||||
|
||||
28 Aug 2025, PHP 8.5.0beta2
|
||||
|
||||
@@ -360,7 +360,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri(
|
||||
base_url = internal_base_url->uri;
|
||||
}
|
||||
|
||||
void *uri = uri_parser->parse_uri(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, should_throw || errors_zv != NULL ? &errors : NULL, !should_throw);
|
||||
void *uri = uri_parser->parse_uri(ZSTR_VAL(uri_str), ZSTR_LEN(uri_str), base_url, errors_zv != NULL ? &errors : NULL, !should_throw);
|
||||
if (UNEXPECTED(uri == NULL)) {
|
||||
if (should_throw) {
|
||||
zval_ptr_dtor(&errors);
|
||||
|
||||
29
ext/uri/tests/101.phpt
Normal file
29
ext/uri/tests/101.phpt
Normal file
@@ -0,0 +1,29 @@
|
||||
--TEST--
|
||||
Test the Lexbor-based URI parser
|
||||
--EXTENSIONS--
|
||||
uri
|
||||
zend_test
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
try {
|
||||
var_dump(zend_test_uri_parser('invalid uri', "Uri\\WhatWg\\Url"));
|
||||
} catch (\Uri\WhatWg\InvalidUrlException $e) {
|
||||
echo $e->getMessage(), PHP_EOL;
|
||||
var_dump($e->errors);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
The specified URI is malformed (MissingSchemeNonRelativeUrl)
|
||||
array(1) {
|
||||
[0]=>
|
||||
object(Uri\WhatWg\UrlValidationError)#%d (3) {
|
||||
["context"]=>
|
||||
string(11) "invalid uri"
|
||||
["type"]=>
|
||||
enum(Uri\WhatWg\UrlValidationErrorType::MissingSchemeNonRelativeUrl)
|
||||
["failure"]=>
|
||||
bool(true)
|
||||
}
|
||||
}
|
||||
@@ -65,19 +65,14 @@ static zend_always_inline void zval_long_or_null_to_lexbor_str(zval *value, lexb
|
||||
*/
|
||||
static const char *fill_errors(zval *errors)
|
||||
{
|
||||
if (errors == NULL) {
|
||||
if (lexbor_parser.log == NULL || lexbor_plog_length(lexbor_parser.log) == 0) {
|
||||
ZVAL_EMPTY_ARRAY(errors);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZEND_ASSERT(Z_ISUNDEF_P(errors));
|
||||
|
||||
array_init(errors);
|
||||
|
||||
if (lexbor_parser.log == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *result = NULL;
|
||||
|
||||
lexbor_plog_entry_t *lxb_error;
|
||||
while ((lxb_error = lexbor_array_obj_pop(&lexbor_parser.log->list)) != NULL) {
|
||||
zval error;
|
||||
@@ -224,7 +219,8 @@ static const char *fill_errors(zval *errors)
|
||||
|
||||
static void throw_invalid_url_exception_during_write(zval *errors, const char *component)
|
||||
{
|
||||
const char *reason = fill_errors(errors);
|
||||
zval err;
|
||||
const char *reason = fill_errors(&err);
|
||||
zend_object *exception = zend_throw_exception_ex(
|
||||
uri_whatwg_invalid_url_exception_ce,
|
||||
0,
|
||||
@@ -234,7 +230,13 @@ static void throw_invalid_url_exception_during_write(zval *errors, const char *c
|
||||
reason ? reason : "",
|
||||
reason ? ")" : ""
|
||||
);
|
||||
zend_update_property(exception->ce, exception, ZEND_STRL("errors"), errors);
|
||||
zend_update_property(exception->ce, exception, ZEND_STRL("errors"), &err);
|
||||
if (errors) {
|
||||
zval_ptr_dtor(errors);
|
||||
ZVAL_COPY_VALUE(errors, &err);
|
||||
} else {
|
||||
zval_ptr_dtor(&err);
|
||||
}
|
||||
}
|
||||
|
||||
static lxb_status_t serialize_to_smart_str_callback(const lxb_char_t *data, size_t length, void *ctx)
|
||||
@@ -561,11 +563,20 @@ lxb_url_t *php_uri_parser_whatwg_parse_ex(const char *uri_str, size_t uri_str_le
|
||||
lxb_url_parser_clean(&lexbor_parser);
|
||||
|
||||
lxb_url_t *url = lxb_url_parse(&lexbor_parser, lexbor_base_url, (unsigned char *) uri_str, uri_str_len);
|
||||
const char *reason = fill_errors(errors);
|
||||
|
||||
if (url == NULL && !silent) {
|
||||
zend_object *exception = zend_throw_exception_ex(uri_whatwg_invalid_url_exception_ce, 0, "The specified URI is malformed%s%s%s", reason ? " (" : "", reason ? reason : "", reason ? ")" : "");
|
||||
zend_update_property(exception->ce, exception, ZEND_STRL("errors"), errors);
|
||||
if ((url == NULL && !silent) || errors != NULL) {
|
||||
zval err;
|
||||
const char *reason = fill_errors(&err);
|
||||
if (url == NULL && !silent) {
|
||||
zend_object *exception = zend_throw_exception_ex(uri_whatwg_invalid_url_exception_ce, 0, "The specified URI is malformed%s%s%s", reason ? " (" : "", reason ? reason : "", reason ? ")" : "");
|
||||
zend_update_property(exception->ce, exception, ZEND_STRL("errors"), &err);
|
||||
}
|
||||
if (errors != NULL) {
|
||||
zval_ptr_dtor(errors);
|
||||
ZVAL_COPY_VALUE(errors, &err);
|
||||
} else {
|
||||
zval_ptr_dtor(&err);
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
|
||||
Reference in New Issue
Block a user