Commit ccd446f2299 for php
commit ccd446f2299012fd3c06b3baf8d1b0dc1f737293
Author: NickSdot <32384907+NickSdot@users.noreply.github.com>
Date: Tue Oct 20 17:06:08 2026 +0700
ext/uri: Refactors builder error handling (#23834)
diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c
index bee17986ca8..030f029ff65 100644
--- a/ext/uri/php_uri_common.c
+++ b/ext/uri/php_uri_common.c
@@ -40,24 +40,17 @@ 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);
-
- /* 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);
+ zend_array_release(errors);
return SUCCESS;
}
- ZEND_TRY_ASSIGN_REF_TMP(errors_zv, errors);
+ ZEND_TRY_ASSIGN_REF_ARR(errors_zv, errors);
if (EG(exception)) {
return FAILURE;
}
diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h
index a1d9d852f3b..a125ef17d1c 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 e0346362423..48ffc767207 100644
--- a/ext/uri/uri_parser_whatwg.c
+++ b/ext/uri/uri_parser_whatwg.c
@@ -977,26 +977,19 @@ 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)
{
- 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;
}
- 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));
+ return fill_errors_inner(errors);
}
-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,
@@ -1006,15 +999,16 @@ ZEND_ATTRIBUTE_NONNULL static void php_uri_parser_whatwg_build_errors_into_excep
zval *error;
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(exception_errors), 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(exception_errors);
- ZVAL_COPY(exception_errors, errors);
+ GC_ADDREF(errors);
+ ZVAL_ARR(exception_errors, errors);
}
}
-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);
@@ -1131,7 +1125,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;
@@ -1148,7 +1142,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;
}
@@ -1161,14 +1155,14 @@ 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;
}
}
- 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;
}
@@ -1176,14 +1170,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);
@@ -1265,7 +1259,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;
}
@@ -1274,7 +1268,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;
}
@@ -1301,27 +1295,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;
}
@@ -1333,7 +1327,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;
}
@@ -1346,14 +1340,14 @@ 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;
}
}
- 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;
}
@@ -1361,7 +1355,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;