From 500069c6b36a98658d8259c86469edf18280389a Mon Sep 17 00:00:00 2001 From: NickSdot Date: Thu, 10 Sep 2026 19:30:12 +0800 Subject: [PATCH 1/6] ext/uri: fixed validation order with new authorities --- ...ultiple_validation_warnings_with_base.phpt | 68 +++++++++++++++++++ ...ss_validation_warning_order_with_base.phpt | 67 ++++++++++++++++++ ext/uri/uri_parser_whatwg.c | 66 ++++++++++++++---- 3 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 ext/uri/tests/whatwg/builder/build_success_multiple_validation_warnings_with_base.phpt create mode 100644 ext/uri/tests/whatwg/builder/build_success_validation_warning_order_with_base.phpt diff --git a/ext/uri/tests/whatwg/builder/build_success_multiple_validation_warnings_with_base.phpt b/ext/uri/tests/whatwg/builder/build_success_multiple_validation_warnings_with_base.phpt new file mode 100644 index 000000000000..01ce4c586d21 --- /dev/null +++ b/ext/uri/tests/whatwg/builder/build_success_multiple_validation_warnings_with_base.phpt @@ -0,0 +1,68 @@ +--TEST-- +Test Uri\WhatWg\UrlBuilder::build() - success - multiple validation warnings with base URL +--FILE-- +setHost('127.0.0.1.') + ->setPath('\newPath') + ->build($base, $errors); + +var_dump($url->toAsciiString()); +var_dump($url); +var_dump($errors); +var_dump($errors == $referenceErrors); +var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString()))); +var_dump($url->equals($reference, Uri\UriComparisonMode::IncludeFragment)); + +?> +--EXPECTF-- +string(25) "https://127.0.0.1/newPath" +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(9) "127.0.0.1" + ["port"]=> + NULL + ["path"]=> + string(8) "/newPath" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +array(2) { + [0]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(8) "\newPath" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::InvalidReverseSoldius) + ["failure"]=> + bool(false) + } + [1]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(0) "" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::Ipv4EmptyPart) + ["failure"]=> + bool(false) + } +} +bool(true) +bool(true) +bool(true) diff --git a/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_with_base.phpt b/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_with_base.phpt new file mode 100644 index 000000000000..27a266b46e86 --- /dev/null +++ b/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_with_base.phpt @@ -0,0 +1,67 @@ +--TEST-- +Test Uri\WhatWg\UrlBuilder::build() - success - validation warning order with base URL +--FILE-- +setUsername('newUser') + ->setPassword('newPass') + ->setHost('127.0.0.1.') + ->setPath('\newPath') + ->build($base, $errors); + +var_dump($url->toAsciiString()); +var_dump($url); +var_dump($errors); +var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString()))); +var_dump($url->equals($reference, Uri\UriComparisonMode::IncludeFragment)); + +?> +--EXPECTF-- +string(41) "https://newUser:newPass@127.0.0.1/newPath" +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(7) "newUser" + ["password"]=> + string(7) "newPass" + ["host"]=> + string(9) "127.0.0.1" + ["port"]=> + NULL + ["path"]=> + string(8) "/newPath" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +array(2) { + [0]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(8) "\newPath" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::InvalidReverseSoldius) + ["failure"]=> + bool(false) + } + [1]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(0) "" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::Ipv4EmptyPart) + ["failure"]=> + bool(false) + } +} +bool(true) +bool(true) diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index 1a258c6c940c..43f2fad8def9 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -990,6 +990,28 @@ ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_errors(zva return fill_errors_inner(Z_ARRVAL_P(errors)); } +ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_reference_errors(zval *errors) +{ + size_t log_len; + if (lexbor_parser.log == NULL || (log_len = lexbor_plog_length(lexbor_parser.log)) == 0) { + return NULL; + } + + zval previous_errors; + ZVAL_COPY_VALUE(&previous_errors, errors); + array_init_size(errors, log_len + zend_hash_num_elements(Z_ARRVAL(previous_errors))); + + const char *reason = fill_errors_inner(Z_ARRVAL_P(errors)); + zval *error; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(previous_errors), error) { + Z_TRY_ADDREF_P(error); + zend_hash_next_index_insert(Z_ARRVAL_P(errors), error); + } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(&previous_errors); + + return reason; +} + ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_exception(zval *errors) { /* Include errors from earlier components in the exception raised by a later component. */ @@ -1050,6 +1072,12 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_fragment_set_null(lxb_u } } +ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_parser_whatwg_build_from_zval_ex( + lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, + const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, + zval *soft_errors_zv, bool reference_errors +); + ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_resolve_reference_from_zval( lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, @@ -1064,8 +1092,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser /* A new authority inherits only the scheme, not the base URL's other components. */ zval base_scheme; php_uri_parser_whatwg_scheme_read(lexbor_base_url, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &base_scheme); - lxb_url_t *url = php_uri_parser_whatwg_build_from_zval(NULL, &base_scheme, - username, password, host, port, path, query, fragment, soft_errors_zv); + lxb_url_t *url = php_uri_parser_whatwg_build_from_zval_ex(NULL, &base_scheme, + username, password, host, port, path, query, fragment, soft_errors_zv, true); zval_ptr_dtor(&base_scheme); return url; } @@ -1255,10 +1283,10 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_whatwg_build_path( return result; } -ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_build_from_zval( +ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_parser_whatwg_build_from_zval_ex( lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, - zval *soft_errors_zv + zval *soft_errors_zv, bool reference_errors ) { lxb_url_parser_clean(&lexbor_parser); @@ -1286,9 +1314,12 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh zval errors; array_init(&errors); + const char *(*build_errors)(zval *) = reference_errors + ? php_uri_parser_whatwg_build_reference_errors + : php_uri_parser_whatwg_build_errors; zend_result result = php_uri_parser_whatwg_scheme_write(lexbor_url, scheme, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1297,7 +1328,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh * Otherwise, preserve the absent host so the path can be opaque. */ if (Z_TYPE_P(host) == IS_STRING || lxb_url_is_special(lexbor_url)) { result = php_uri_parser_whatwg_host_write(lexbor_url, host, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1324,27 +1355,27 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh /* Intentionally writing username after host to avoid error when the username is set but the host is missing */ result = php_uri_parser_whatwg_username_write(lexbor_url, username, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } /* Intentionally writing password after host to avoid error when the password is set but the password is missing */ result = php_uri_parser_whatwg_password_write(lexbor_url, password, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } /* Intentionally writing port after host to avoid error when the port is set but the host is missing */ result = php_uri_parser_whatwg_port_write(lexbor_url, port, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } result = php_uri_parser_whatwg_build_path(lexbor_url, path, query, fragment, &errors); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1356,7 +1387,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh lexbor_str_init(&lexbor_url->query, lexbor_url->mraw, 1); } else { result = php_uri_parser_whatwg_query_write(lexbor_url, query, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1369,7 +1400,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh lexbor_str_init(&lexbor_url->fragment, lexbor_url->mraw, 1); } else { result = php_uri_parser_whatwg_fragment_write(lexbor_url, fragment, NULL); - php_uri_parser_whatwg_build_errors(&errors); + build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1390,6 +1421,17 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh return NULL; } +ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_build_from_zval( + lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, + const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, + zval *soft_errors_zv +) { + return php_uri_parser_whatwg_build_from_zval_ex( + lexbor_base_url, scheme, username, password, host, port, path, query, fragment, + soft_errors_zv, false + ); +} + PHPAPI const php_uri_parser php_uri_parser_whatwg = { .name = PHP_URI_PARSER_WHATWG, .parse = php_uri_parser_whatwg_parse, From 2189ad665ff7a07c564f8acab13415598fb9d681 Mon Sep 17 00:00:00 2001 From: NickSdot Date: Mon, 21 Sep 2026 20:28:57 +0800 Subject: [PATCH 2/6] ext/uri: fixed validation order with existing authorities --- .../build_success_soft_errors_with_base.phpt | 6 +- ...ing_order_without_authority_with_base.phpt | 71 +++++++++++++++++++ ext/uri/uri_parser_whatwg.c | 12 ++-- 3 files changed, 81 insertions(+), 8 deletions(-) create mode 100644 ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_authority_with_base.phpt diff --git a/ext/uri/tests/whatwg/builder/build_success_soft_errors_with_base.phpt b/ext/uri/tests/whatwg/builder/build_success_soft_errors_with_base.phpt index 7f2b37146627..c4baff32ce59 100644 --- a/ext/uri/tests/whatwg/builder/build_success_soft_errors_with_base.phpt +++ b/ext/uri/tests/whatwg/builder/build_success_soft_errors_with_base.phpt @@ -25,7 +25,8 @@ array(2) { [0]=> object(Uri\WhatWg\UrlValidationError)#%d (%d) { ["context"]=> - string(2) " b" + string(2) " +y" ["type"]=> enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit) ["failure"]=> @@ -34,8 +35,7 @@ array(2) { [1]=> object(Uri\WhatWg\UrlValidationError)#%d (%d) { ["context"]=> - string(2) " -y" + string(2) " b" ["type"]=> enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit) ["failure"]=> diff --git a/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_authority_with_base.phpt b/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_authority_with_base.phpt new file mode 100644 index 000000000000..785bb6fba40b --- /dev/null +++ b/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_authority_with_base.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test Uri\WhatWg\UrlBuilder::build() - success - validation warning order without authority and with base URL +--FILE-- +setPath('/foo\bar') + ->setFragment('%') + ->build($base, $errors); + +var_dump($url->toAsciiString()); +var_dump($url); +var_dump($errors); +var_dump( + array_map(static fn($error) => $error->type, $errors) + === array_map(static fn($error) => $error->type, $referenceErrors) +); +var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString()))); +var_dump($url->equals($reference, Uri\UriComparisonMode::IncludeFragment)); + +?> +--EXPECTF-- +string(29) "https://example.com/foo/bar#%" +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + NULL + ["path"]=> + string(8) "/foo/bar" + ["query"]=> + NULL + ["fragment"]=> + string(1) "%" +} +array(2) { + [0]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(1) "%" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit) + ["failure"]=> + bool(false) + } + [1]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(4) "\bar" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::InvalidReverseSoldius) + ["failure"]=> + bool(false) + } +} +bool(true) +bool(true) +bool(true) diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index 43f2fad8def9..b348bfddedef 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -1033,12 +1033,14 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_excep } } -ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_and_throw(const lxb_status_t status, const char *component, zval *errors) +ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_reference_errors_and_throw( + const lxb_status_t status, const char *component, zval *errors +) { if (status != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(NULL, component); } else { - php_uri_parser_whatwg_build_errors(errors); + php_uri_parser_whatwg_build_reference_errors(errors); } } @@ -1182,7 +1184,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser lxb_url_parser_clean(&lexbor_parser); status = lxb_url_parse_basic(&lexbor_parser, lexbor_url, lexbor_base_url, (const lxb_char_t *) ZSTR_VAL(input), ZSTR_LEN(input), state, LXB_ENCODING_UTF_8); - php_uri_parser_whatwg_build_errors_and_throw(status, "path", &errors); + php_uri_parser_whatwg_build_reference_errors_and_throw(status, "path", &errors); zend_string_release(input); if (status != LXB_STATUS_OK) { goto failure; @@ -1199,7 +1201,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser (lxb_char_t *) Z_STRVAL_P(query), Z_STRLEN_P(query), LXB_URL_STATE_QUERY_STATE, LXB_ENCODING_AUTO ); - php_uri_parser_whatwg_build_errors_and_throw(status, "query", &errors); + php_uri_parser_whatwg_build_reference_errors_and_throw(status, "query", &errors); if (status != LXB_STATUS_OK) { goto failure; } @@ -1212,7 +1214,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser (lxb_char_t *) Z_STRVAL_P(fragment), Z_STRLEN_P(fragment), LXB_URL_STATE_FRAGMENT_STATE, LXB_ENCODING_AUTO ); - php_uri_parser_whatwg_build_errors_and_throw(status, "fragment", &errors); + php_uri_parser_whatwg_build_reference_errors_and_throw(status, "fragment", &errors); if (status != LXB_STATUS_OK) { goto failure; } From 09eb70005e404e04cbc49c39576567b68bd200ef Mon Sep 17 00:00:00 2001 From: NickSdot Date: Mon, 21 Sep 2026 21:14:12 +0800 Subject: [PATCH 3/6] ext/uri: fixed standalone builder validation order --- ..._error_soft_errors_reset_without_base.phpt | 25 ++++-- ...validation_warning_order_without_base.phpt | 67 ++++++++++++++++ ext/uri/uri_parser_whatwg.c | 79 ++++++------------- 3 files changed, 110 insertions(+), 61 deletions(-) create mode 100644 ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_base.phpt diff --git a/ext/uri/tests/whatwg/builder/build_error_soft_errors_reset_without_base.phpt b/ext/uri/tests/whatwg/builder/build_error_soft_errors_reset_without_base.phpt index f43ab31164bf..a9fa607b5a9f 100644 --- a/ext/uri/tests/whatwg/builder/build_error_soft_errors_reset_without_base.phpt +++ b/ext/uri/tests/whatwg/builder/build_error_soft_errors_reset_without_base.phpt @@ -3,6 +3,14 @@ Test Uri\WhatWg\UrlBuilder::build() - error - clears soft errors when an excepti --FILE-- errors; +} + $builder = new Uri\WhatWg\UrlBuilder(); $builder->setScheme("ht\ttps"); $builder->setHost(null); @@ -13,6 +21,10 @@ try { } catch (Throwable $e) { echo $e::class, ': ', $e->getMessage(), "\n"; var_dump($e->errors); + var_dump( + array_map(static fn($error) => $error->type, $e->errors) + === array_map(static fn($error) => $error->type, $referenceErrors) + ); } var_dump($softErrors); @@ -24,21 +36,22 @@ array(2) { [0]=> object(Uri\WhatWg\UrlValidationError)#%d (%d) { ["context"]=> - string(4) " tps" + string(0) "" ["type"]=> - enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit) + enum(Uri\WhatWg\UrlValidationErrorType::HostMissing) ["failure"]=> - bool(false) + bool(true) } [1]=> object(Uri\WhatWg\UrlValidationError)#%d (%d) { ["context"]=> - string(0) "" + string(4) " tps" ["type"]=> - enum(Uri\WhatWg\UrlValidationErrorType::HostMissing) + enum(Uri\WhatWg\UrlValidationErrorType::InvalidUrlUnit) ["failure"]=> - bool(true) + bool(false) } } +bool(true) array(0) { } diff --git a/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_base.phpt b/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_base.phpt new file mode 100644 index 000000000000..8615b2a7546c --- /dev/null +++ b/ext/uri/tests/whatwg/builder/build_success_validation_warning_order_without_base.phpt @@ -0,0 +1,67 @@ +--TEST-- +Test Uri\WhatWg\UrlBuilder::build() - success - validation warning order without base URL +--FILE-- +setScheme('https') + ->setHost('127.0.0.1.') + ->setPath('\newPath') + ->build(null, $errors); + +var_dump($url->toAsciiString()); +var_dump($url); +var_dump($errors); +var_dump($errors == $referenceErrors); +var_dump($url->equals(new Uri\WhatWg\Url($url->toAsciiString()))); +var_dump($url->equals($reference, Uri\UriComparisonMode::IncludeFragment)); + +?> +--EXPECTF-- +string(25) "https://127.0.0.1/newPath" +object(Uri\WhatWg\Url)#%d (%d) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(9) "127.0.0.1" + ["port"]=> + NULL + ["path"]=> + string(8) "/newPath" + ["query"]=> + NULL + ["fragment"]=> + NULL +} +array(2) { + [0]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(8) "\newPath" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::InvalidReverseSoldius) + ["failure"]=> + bool(false) + } + [1]=> + object(Uri\WhatWg\UrlValidationError)#%d (%d) { + ["context"]=> + string(0) "" + ["type"]=> + enum(Uri\WhatWg\UrlValidationErrorType::Ipv4EmptyPart) + ["failure"]=> + bool(false) + } +} +bool(true) +bool(true) +bool(true) diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index b348bfddedef..17f3d2809ec1 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -976,23 +976,10 @@ ZEND_ATTRIBUTE_NONNULL static lxb_url_scheme_type_t php_uri_parser_whatwg_get_sp ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_errors(zval *errors) { - size_t log_len; - - if (lexbor_parser.log == NULL || (log_len = lexbor_plog_length(lexbor_parser.log)) == 0) { - return NULL; - } - - if (Z_TYPE_P(errors) != IS_ARRAY) { - zval_ptr_dtor(errors); - array_init_size(errors, log_len); - } - - return fill_errors_inner(Z_ARRVAL_P(errors)); -} + ZEND_ASSERT(Z_TYPE_P(errors) == IS_ARRAY); -ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_reference_errors(zval *errors) -{ size_t log_len; + if (lexbor_parser.log == NULL || (log_len = lexbor_plog_length(lexbor_parser.log)) == 0) { return NULL; } @@ -1021,26 +1008,22 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_excep zval *exception_errors = zend_read_property(php_uri_ce_whatwg_invalid_url_exception, EG(exception), ZEND_STRL("errors"), true, &rv); ZEND_ASSERT(Z_TYPE_P(exception_errors) == IS_ARRAY); + SEPARATE_ARRAY(exception_errors); zval *error; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(exception_errors), error) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(errors), error) { Z_TRY_ADDREF_P(error); - zend_hash_next_index_insert(Z_ARRVAL_P(errors), error); + zend_hash_next_index_insert(Z_ARRVAL_P(exception_errors), error); } ZEND_HASH_FOREACH_END(); - - zval_ptr_dtor(exception_errors); - ZVAL_COPY(exception_errors, errors); } } -ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_reference_errors_and_throw( - const lxb_status_t status, const char *component, zval *errors -) +ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_and_throw(const lxb_status_t status, const char *component, zval *errors) { if (status != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(NULL, component); } else { - php_uri_parser_whatwg_build_reference_errors(errors); + php_uri_parser_whatwg_build_errors(errors); } } @@ -1074,10 +1057,10 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_fragment_set_null(lxb_u } } -ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_parser_whatwg_build_from_zval_ex( +ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_build_from_zval( lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, - zval *soft_errors_zv, bool reference_errors + zval *soft_errors_zv ); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_resolve_reference_from_zval( @@ -1094,8 +1077,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser /* A new authority inherits only the scheme, not the base URL's other components. */ zval base_scheme; php_uri_parser_whatwg_scheme_read(lexbor_base_url, PHP_URI_COMPONENT_READ_MODE_NORMALIZED_ASCII, &base_scheme); - lxb_url_t *url = php_uri_parser_whatwg_build_from_zval_ex(NULL, &base_scheme, - username, password, host, port, path, query, fragment, soft_errors_zv, true); + lxb_url_t *url = php_uri_parser_whatwg_build_from_zval(NULL, &base_scheme, + username, password, host, port, path, query, fragment, soft_errors_zv); zval_ptr_dtor(&base_scheme); return url; } @@ -1184,7 +1167,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser lxb_url_parser_clean(&lexbor_parser); status = lxb_url_parse_basic(&lexbor_parser, lexbor_url, lexbor_base_url, (const lxb_char_t *) ZSTR_VAL(input), ZSTR_LEN(input), state, LXB_ENCODING_UTF_8); - php_uri_parser_whatwg_build_reference_errors_and_throw(status, "path", &errors); + php_uri_parser_whatwg_build_errors_and_throw(status, "path", &errors); zend_string_release(input); if (status != LXB_STATUS_OK) { goto failure; @@ -1201,7 +1184,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser (lxb_char_t *) Z_STRVAL_P(query), Z_STRLEN_P(query), LXB_URL_STATE_QUERY_STATE, LXB_ENCODING_AUTO ); - php_uri_parser_whatwg_build_reference_errors_and_throw(status, "query", &errors); + php_uri_parser_whatwg_build_errors_and_throw(status, "query", &errors); if (status != LXB_STATUS_OK) { goto failure; } @@ -1214,7 +1197,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser (lxb_char_t *) Z_STRVAL_P(fragment), Z_STRLEN_P(fragment), LXB_URL_STATE_FRAGMENT_STATE, LXB_ENCODING_AUTO ); - php_uri_parser_whatwg_build_reference_errors_and_throw(status, "fragment", &errors); + php_uri_parser_whatwg_build_errors_and_throw(status, "fragment", &errors); if (status != LXB_STATUS_OK) { goto failure; } @@ -1285,10 +1268,10 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_whatwg_build_path( return result; } -ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_parser_whatwg_build_from_zval_ex( +ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_build_from_zval( lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, - zval *soft_errors_zv, bool reference_errors + zval *soft_errors_zv ) { lxb_url_parser_clean(&lexbor_parser); @@ -1316,12 +1299,9 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_pa zval errors; array_init(&errors); - const char *(*build_errors)(zval *) = reference_errors - ? php_uri_parser_whatwg_build_reference_errors - : php_uri_parser_whatwg_build_errors; zend_result result = php_uri_parser_whatwg_scheme_write(lexbor_url, scheme, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1330,7 +1310,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_pa * Otherwise, preserve the absent host so the path can be opaque. */ if (Z_TYPE_P(host) == IS_STRING || lxb_url_is_special(lexbor_url)) { result = php_uri_parser_whatwg_host_write(lexbor_url, host, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1357,27 +1337,27 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_pa /* Intentionally writing username after host to avoid error when the username is set but the host is missing */ result = php_uri_parser_whatwg_username_write(lexbor_url, username, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } /* Intentionally writing password after host to avoid error when the password is set but the password is missing */ result = php_uri_parser_whatwg_password_write(lexbor_url, password, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } /* Intentionally writing port after host to avoid error when the port is set but the host is missing */ result = php_uri_parser_whatwg_port_write(lexbor_url, port, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } result = php_uri_parser_whatwg_build_path(lexbor_url, path, query, fragment, &errors); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1389,7 +1369,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_pa lexbor_str_init(&lexbor_url->query, lexbor_url->mraw, 1); } else { result = php_uri_parser_whatwg_query_write(lexbor_url, query, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1402,7 +1382,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_pa lexbor_str_init(&lexbor_url->fragment, lexbor_url->mraw, 1); } else { result = php_uri_parser_whatwg_fragment_write(lexbor_url, fragment, NULL); - build_errors(&errors); + php_uri_parser_whatwg_build_errors(&errors); if (result == FAILURE) { goto failure; } @@ -1423,17 +1403,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) static lxb_url_t *php_uri_pa return NULL; } -ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_whatwg_build_from_zval( - lxb_url_t *lexbor_base_url, const zval *scheme, const zval *username, const zval *password, - const zval *host, const zval *port, const zval *path, const zval *query, const zval *fragment, - zval *soft_errors_zv -) { - return php_uri_parser_whatwg_build_from_zval_ex( - lexbor_base_url, scheme, username, password, host, port, path, query, fragment, - soft_errors_zv, false - ); -} - PHPAPI const php_uri_parser php_uri_parser_whatwg = { .name = PHP_URI_PARSER_WHATWG, .parse = php_uri_parser_whatwg_parse, From a89a3bb56bd1fbb445246d8885363ea98451e228 Mon Sep 17 00:00:00 2001 From: NickSdot Date: Tue, 22 Sep 2026 00:03:19 +0800 Subject: [PATCH 4/6] review: inlined zval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Düsterhus <209270+TimWolla@users.noreply.github.com> --- ext/uri/uri_parser_whatwg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index 17f3d2809ec1..2895801d7695 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -989,8 +989,7 @@ ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_errors(zva array_init_size(errors, log_len + zend_hash_num_elements(Z_ARRVAL(previous_errors))); const char *reason = fill_errors_inner(Z_ARRVAL_P(errors)); - zval *error; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL(previous_errors), error) { + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(previous_errors), zval *error) { Z_TRY_ADDREF_P(error); zend_hash_next_index_insert(Z_ARRVAL_P(errors), error); } ZEND_HASH_FOREACH_END(); From a09e8a60fbbf64743b116e9bf3cf2b94f8adf0b4 Mon Sep 17 00:00:00 2001 From: NickSdot Date: Tue, 22 Sep 2026 08:54:18 +0800 Subject: [PATCH 5/6] review: hash tables --- ext/uri/uri_parser_whatwg.c | 62 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index 2895801d7695..44105584575a 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -974,34 +974,32 @@ ZEND_ATTRIBUTE_NONNULL static lxb_url_scheme_type_t php_uri_parser_whatwg_get_sp return LXB_URL_SCHEMEL_TYPE__UNDEF; } -ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_errors(zval *errors) +ZEND_ATTRIBUTE_NONNULL static const char *php_uri_parser_whatwg_build_errors(HashTable *errors) { - ZEND_ASSERT(Z_TYPE_P(errors) == IS_ARRAY); - - size_t log_len; - - if (lexbor_parser.log == NULL || (log_len = lexbor_plog_length(lexbor_parser.log)) == 0) { + if (lexbor_parser.log == NULL || lexbor_plog_length(lexbor_parser.log) == 0) { return NULL; } - zval previous_errors; - ZVAL_COPY_VALUE(&previous_errors, errors); - array_init_size(errors, log_len + zend_hash_num_elements(Z_ARRVAL(previous_errors))); + if (zend_hash_num_elements(errors) == 0) { + return fill_errors_inner(errors); + } - const char *reason = fill_errors_inner(Z_ARRVAL_P(errors)); - ZEND_HASH_FOREACH_VAL(Z_ARRVAL(previous_errors), zval *error) { + HashTable *previous_errors = zend_array_dup(errors); + zend_hash_clean(errors); + const char *reason = fill_errors_inner(errors); + ZEND_HASH_FOREACH_VAL(previous_errors, zval *error) { Z_TRY_ADDREF_P(error); - zend_hash_next_index_insert(Z_ARRVAL_P(errors), error); + zend_hash_next_index_insert(errors, error); } ZEND_HASH_FOREACH_END(); - zval_ptr_dtor(&previous_errors); + zend_array_destroy(previous_errors); return reason; } -ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_exception(zval *errors) +ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_exception(HashTable *errors) { /* Include errors from earlier components in the exception raised by a later component. */ - if (zend_hash_num_elements(Z_ARRVAL_P(errors)) > 0 && EG(exception) + if (zend_hash_num_elements(errors) > 0 && EG(exception) && instanceof_function(EG(exception)->ce, php_uri_ce_whatwg_invalid_url_exception)) { zval rv; zval *exception_errors = zend_read_property(php_uri_ce_whatwg_invalid_url_exception, @@ -1010,14 +1008,14 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_excep SEPARATE_ARRAY(exception_errors); zval *error; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(errors), error) { + ZEND_HASH_FOREACH_VAL(errors, error) { Z_TRY_ADDREF_P(error); zend_hash_next_index_insert(Z_ARRVAL_P(exception_errors), error); } ZEND_HASH_FOREACH_END(); } } -ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_and_throw(const lxb_status_t status, const char *component, zval *errors) +ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_and_throw(const lxb_status_t status, const char *component, HashTable *errors) { if (status != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(NULL, component); @@ -1166,7 +1164,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser lxb_url_parser_clean(&lexbor_parser); status = lxb_url_parse_basic(&lexbor_parser, lexbor_url, lexbor_base_url, (const lxb_char_t *) ZSTR_VAL(input), ZSTR_LEN(input), state, LXB_ENCODING_UTF_8); - php_uri_parser_whatwg_build_errors_and_throw(status, "path", &errors); + php_uri_parser_whatwg_build_errors_and_throw(status, "path", Z_ARRVAL(errors)); zend_string_release(input); if (status != LXB_STATUS_OK) { goto failure; @@ -1183,7 +1181,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser (lxb_char_t *) Z_STRVAL_P(query), Z_STRLEN_P(query), LXB_URL_STATE_QUERY_STATE, LXB_ENCODING_AUTO ); - php_uri_parser_whatwg_build_errors_and_throw(status, "query", &errors); + php_uri_parser_whatwg_build_errors_and_throw(status, "query", Z_ARRVAL(errors)); if (status != LXB_STATUS_OK) { goto failure; } @@ -1196,7 +1194,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser (lxb_char_t *) Z_STRVAL_P(fragment), Z_STRLEN_P(fragment), LXB_URL_STATE_FRAGMENT_STATE, LXB_ENCODING_AUTO ); - php_uri_parser_whatwg_build_errors_and_throw(status, "fragment", &errors); + php_uri_parser_whatwg_build_errors_and_throw(status, "fragment", Z_ARRVAL(errors)); if (status != LXB_STATUS_OK) { goto failure; } @@ -1211,14 +1209,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser return lexbor_url; failure: - php_uri_parser_whatwg_build_errors_into_exception(&errors); + php_uri_parser_whatwg_build_errors_into_exception(Z_ARRVAL(errors)); zval_ptr_dtor(&errors); lxb_url_destroy(lexbor_url); return NULL; } ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_whatwg_build_path( - lxb_url_t *lexbor_url, const zval *path, const zval *query, const zval *fragment, zval *errors + lxb_url_t *lexbor_url, const zval *path, const zval *query, const zval *fragment, HashTable *errors ) { zend_result result; const char *path_start = Z_STRVAL_P(path); @@ -1300,7 +1298,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh array_init(&errors); zend_result result = php_uri_parser_whatwg_scheme_write(lexbor_url, scheme, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } @@ -1309,7 +1307,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh * Otherwise, preserve the absent host so the path can be opaque. */ if (Z_TYPE_P(host) == IS_STRING || lxb_url_is_special(lexbor_url)) { result = php_uri_parser_whatwg_host_write(lexbor_url, host, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } @@ -1336,27 +1334,27 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh /* Intentionally writing username after host to avoid error when the username is set but the host is missing */ result = php_uri_parser_whatwg_username_write(lexbor_url, username, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } /* Intentionally writing password after host to avoid error when the password is set but the password is missing */ result = php_uri_parser_whatwg_password_write(lexbor_url, password, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } /* Intentionally writing port after host to avoid error when the port is set but the host is missing */ result = php_uri_parser_whatwg_port_write(lexbor_url, port, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } - result = php_uri_parser_whatwg_build_path(lexbor_url, path, query, fragment, &errors); - php_uri_parser_whatwg_build_errors(&errors); + result = php_uri_parser_whatwg_build_path(lexbor_url, path, query, fragment, Z_ARRVAL(errors)); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } @@ -1368,7 +1366,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh lexbor_str_init(&lexbor_url->query, lexbor_url->mraw, 1); } else { result = php_uri_parser_whatwg_query_write(lexbor_url, query, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } @@ -1381,7 +1379,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh lexbor_str_init(&lexbor_url->fragment, lexbor_url->mraw, 1); } else { result = php_uri_parser_whatwg_fragment_write(lexbor_url, fragment, NULL); - php_uri_parser_whatwg_build_errors(&errors); + php_uri_parser_whatwg_build_errors(Z_ARRVAL(errors)); if (result == FAILURE) { goto failure; } @@ -1396,7 +1394,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh return lexbor_url; failure: ZEND_ASSERT(EG(exception)); - php_uri_parser_whatwg_build_errors_into_exception(&errors); + php_uri_parser_whatwg_build_errors_into_exception(Z_ARRVAL(errors)); zval_ptr_dtor(&errors); lxb_url_destroy(lexbor_url); return NULL; From ada53f14c12bf39b34b327c5491e61da3eb87292 Mon Sep 17 00:00:00 2001 From: NickSdot Date: Tue, 22 Sep 2026 09:00:24 +0800 Subject: [PATCH 6/6] review: dead error state --- ext/uri/php_uri_common.c | 20 ++++++++------------ ext/uri/php_uri_common.h | 2 +- ext/uri/uri_parser_whatwg.c | 8 ++++---- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index e4850d8059ee..bd498d58f09c 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -40,24 +40,20 @@ static zend_string *get_known_string_by_property_name(php_uri_property_name prop } } -zend_result php_uri_pass_errors_by_ref_and_free(zval *errors_zv, zval *errors) +ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result php_uri_pass_errors_by_ref_and_free(zval *errors_zv, HashTable *errors) { - ZEND_ASSERT(Z_TYPE_P(errors) == IS_UNDEF || Z_TYPE_P(errors) == IS_ARRAY); + zval errors_tmp; + ZVAL_ARR(&errors_tmp, errors); - /* There was no error during parsing */ - if (Z_ISUNDEF_P(errors)) { - return SUCCESS; - } - - /* The errors parameter is an array, but the pass-by ref argument stored by - * errors_zv was not passed - the URI implementation either doesn't support - * returning additional error information, or the caller is not interested in it */ + /* The pass-by ref argument stored by errors_zv was not passed - the URI + * implementation either doesn't support returning additional error information, + * or the caller is not interested in it */ if (errors_zv == NULL) { - zval_ptr_dtor(errors); + zval_ptr_dtor(&errors_tmp); return SUCCESS; } - ZEND_TRY_ASSIGN_REF_TMP(errors_zv, errors); + ZEND_TRY_ASSIGN_REF_TMP(errors_zv, &errors_tmp); if (EG(exception)) { return FAILURE; } diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index a1d9d852f3b7..a125ef17d1c4 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -188,7 +188,7 @@ static inline const php_uri_property_handler *php_uri_parser_property_handler_by } } -zend_result php_uri_pass_errors_by_ref_and_free(zval *errors_zv, zval *errors); +ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result php_uri_pass_errors_by_ref_and_free(zval *errors_zv, HashTable *errors); void php_uri_property_read_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode); void php_uri_property_write_str_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); void php_uri_property_write_str_or_null_helper(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index 44105584575a..ddbf0ae6752c 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -1200,8 +1200,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser } } - if (php_uri_pass_errors_by_ref_and_free(soft_errors_zv, &errors) == FAILURE) { - /* The errors zval was already consumed; goto failure would destroy it again. */ + if (php_uri_pass_errors_by_ref_and_free(soft_errors_zv, Z_ARRVAL(errors)) == FAILURE) { + /* The errors array was already consumed; goto failure would destroy it again. */ lxb_url_destroy(lexbor_url); return NULL; } @@ -1385,8 +1385,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(2, 3, 4, 5, 6, 7, 8, 9) lxb_url_t *php_uri_parser_wh } } - if (php_uri_pass_errors_by_ref_and_free(soft_errors_zv, &errors) == FAILURE) { - /* The errors zval was already consumed; goto failure would destroy it again. */ + if (php_uri_pass_errors_by_ref_and_free(soft_errors_zv, Z_ARRVAL(errors)) == FAILURE) { + /* The errors array was already consumed; goto failure would destroy it again. */ lxb_url_destroy(lexbor_url); return NULL; }