Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion ext/uri/php_uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 29 additions & 0 deletions ext/uri/tests/101.phpt
Original file line number Diff line number Diff line change
@@ -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)
}
}
39 changes: 25 additions & 14 deletions ext/uri/uri_parser_whatwg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
Loading