From 2ad0b5cf052eba0c3c16fb0800fafe74412e8629 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Wed, 10 Sep 2025 21:28:23 +0200 Subject: [PATCH 1/7] Fix GH-19792: SCCP causes UAF for return value if both warning and exception are triggered If an exception _and_ a warning (or deprecation) is emitted, then the result is destroyed twice. Use an `else if` to prevent this. This is tested via zend_test because the deprecation that triggered the original reproducer may disappear in the future. Closes GH-19793. --- NEWS | 2 ++ Zend/Optimizer/sccp.c | 4 +--- ext/opcache/tests/opt/gh19792.phpt | 27 +++++++++++++++++++++++++++ ext/zend_test/test.c | 9 +++++++++ ext/zend_test/test.stub.php | 3 +++ ext/zend_test/test_arginfo.h | 6 +++++- 6 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 ext/opcache/tests/opt/gh19792.phpt diff --git a/NEWS b/NEWS index 1af55dd4c84f8..9f97a6985f9ed 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Fixed bug GH-19765 (object_properties_load() bypasses readonly property checks). (timwolla) . Fixed hard_timeout with --enable-zend-max-execution-timers. (Appla) + . Fixed bug GH-19792 (SCCP causes UAF for return value if both warning and + exception are triggered). (nielsdos) - Standard: . Fixed bug GH-12265 (Cloning an object breaks serialization recursion). diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index d5486803e19a6..4b7a77abb0911 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -842,9 +842,7 @@ static inline zend_result ct_eval_func_call( zval_ptr_dtor(result); zend_clear_exception(); retval = FAILURE; - } - - if (EG(capture_warnings_during_sccp) > 1) { + } else if (EG(capture_warnings_during_sccp) > 1) { zval_ptr_dtor(result); retval = FAILURE; } diff --git a/ext/opcache/tests/opt/gh19792.phpt b/ext/opcache/tests/opt/gh19792.phpt new file mode 100644 index 0000000000000..edd805ca57a19 --- /dev/null +++ b/ext/opcache/tests/opt/gh19792.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-19792 (SCCP causes UAF for return value if both warning and exception are triggered) +--EXTENSIONS-- +opcache +zend_test +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECTF-- +Warning: a warning in %s on line %d +an exception diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index e7bb97cb44abb..67150d47b0441 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -1528,3 +1528,12 @@ static PHP_FUNCTION(zend_test_gh18756) zend_mm_gc(heap); zend_mm_shutdown(heap, true, false); } + +static PHP_FUNCTION(zend_test_gh19792) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + RETVAL_STRING("this is a non-interned string"); + zend_error(E_WARNING, "a warning"); + zend_throw_error(NULL, "an exception"); +} diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index f9cb93b5a1ccb..290f55976d169 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -264,6 +264,9 @@ function zend_test_is_zend_ptr(int $addr): bool {} function zend_test_log_err_debug(string $str): void {} function zend_test_gh18756(): void {} + + /** @compile-time-eval */ + function zend_test_gh19792(): void {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index c7e3df5c58d24..cccd4608d9829 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 2f161861ab09b6b5b594dc2db7c2c9df49d76aa7 */ + * Stub hash: fa769dbbf7ba1d10f0141fed6a45fc06a84cd94c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -164,6 +164,8 @@ ZEND_END_ARG_INFO() #define arginfo_zend_test_gh18756 arginfo_zend_test_void_return +#define arginfo_zend_test_gh19792 arginfo_zend_test_void_return + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -295,6 +297,7 @@ static ZEND_FUNCTION(zend_test_cast_fread); static ZEND_FUNCTION(zend_test_is_zend_ptr); static ZEND_FUNCTION(zend_test_log_err_debug); static ZEND_FUNCTION(zend_test_gh18756); +static ZEND_FUNCTION(zend_test_gh19792); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -376,6 +379,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr) ZEND_FE(zend_test_log_err_debug, arginfo_zend_test_log_err_debug) ZEND_FE(zend_test_gh18756, arginfo_zend_test_gh18756) + ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(zend_test_gh19792, arginfo_zend_test_gh19792) ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func) ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func) ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func) From 4974d5ef49f4467ce183df73ffa85493cff93712 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Mon, 8 Sep 2025 18:55:47 +0200 Subject: [PATCH 2/7] Fix GH-19701: Serialize/deserialize loses some data See GH-19701 for discussion. This now restores the (correct) serialization output from versions PHP 7.4.1 and below. Closes GH-19762. --- NEWS | 1 + ext/standard/tests/serialize/gh19701.phpt | 30 +++++++++++++++++++++++ ext/standard/var.c | 9 +------ 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 ext/standard/tests/serialize/gh19701.phpt diff --git a/NEWS b/NEWS index 9f97a6985f9ed..28b811682f2cd 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,7 @@ PHP NEWS - Standard: . Fixed bug GH-12265 (Cloning an object breaks serialization recursion). (nielsdos) + . Fixed bug GH-19701 (Serialize/deserialize loses some data). (nielsdos) - Zip: . Fixed bug GH-19688 (Remove pattern overflow in zip addGlob()). (nielsdos) diff --git a/ext/standard/tests/serialize/gh19701.phpt b/ext/standard/tests/serialize/gh19701.phpt new file mode 100644 index 0000000000000..a1a3fd5c64bcc --- /dev/null +++ b/ext/standard/tests/serialize/gh19701.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-19701 (Serialize/deserialize loses some data) +--CREDITS-- +cuchac +DanielEScherzer +--FILE-- +parent = $baseProduct; +$baseProduct->children = [ $child ]; + +$data = [clone $baseProduct, $baseProduct]; + +echo serialize($data), "\n"; + +?> +--EXPECT-- +a:2:{i:0;O:4:"Item":2:{s:8:"children";a:1:{i:0;O:4:"Item":2:{s:8:"children";a:0:{}s:6:"parent";O:4:"Item":2:{s:8:"children";a:1:{i:0;r:4;}s:6:"parent";N;}}}s:6:"parent";N;}i:1;r:6;} diff --git a/ext/standard/var.c b/ext/standard/var.c index b7dc6dff1d884..c6e280d15ab93 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -954,18 +954,11 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable /* we should still add element even if it's not OK, * since we already wrote the length of the array before */ if (Z_TYPE_P(data) == IS_ARRAY) { - if (UNEXPECTED(Z_IS_RECURSIVE_P(data)) - || UNEXPECTED(Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))) { + if (UNEXPECTED(Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))) { php_add_var_hash(var_hash, struc, in_rcn_array); smart_str_appendl(buf, "N;", 2); } else { - if (Z_REFCOUNTED_P(data)) { - Z_PROTECT_RECURSION_P(data); - } php_var_serialize_intern(buf, data, var_hash, in_rcn_array, false); - if (Z_REFCOUNTED_P(data)) { - Z_UNPROTECT_RECURSION_P(data); - } } } else { php_var_serialize_intern(buf, data, var_hash, in_rcn_array, false); From 62660e62755a213393037121f8ad85b881259468 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 11 Sep 2025 21:24:09 +0200 Subject: [PATCH 3/7] [ci skip] Fix missing deprecation in output --- ext/standard/tests/serialize/gh19701.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/standard/tests/serialize/gh19701.phpt b/ext/standard/tests/serialize/gh19701.phpt index a1a3fd5c64bcc..a8c1d53c6e376 100644 --- a/ext/standard/tests/serialize/gh19701.phpt +++ b/ext/standard/tests/serialize/gh19701.phpt @@ -26,5 +26,6 @@ $data = [clone $baseProduct, $baseProduct]; echo serialize($data), "\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: The __sleep() serialization magic method has been deprecated. Implement __serialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d a:2:{i:0;O:4:"Item":2:{s:8:"children";a:1:{i:0;O:4:"Item":2:{s:8:"children";a:0:{}s:6:"parent";O:4:"Item":2:{s:8:"children";a:1:{i:0;r:4;}s:6:"parent";N;}}}s:6:"parent";N;}i:1;r:6;} From 74048290851b79481f4af96c84e11257ebe04e65 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 11 Sep 2025 21:54:41 +0200 Subject: [PATCH 4/7] uri: Remove outdated docs in WhatWG uri parser (#19806) [ci skip] --- ext/uri/uri_parser_whatwg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index ad31d1d12b5b8..2209db0393426 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -59,9 +59,6 @@ static zend_always_inline void zval_long_or_null_to_lexbor_str(zval *value, lexb * Creates a Uri\WhatWg\UrlValidationError class by mapping error codes listed in * https://url.spec.whatwg.org/#writing to a Uri\WhatWg\UrlValidationErrorType enum. * The result is passed by reference to the errors parameter. - * - * When errors is NULL, the caller is not interested in the additional error information, - * so the function does nothing. */ static const char *fill_errors(zval *errors) { From 04deb4df62211dd1c3dc6d9f87530e7f27c0172e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 11 Sep 2025 21:58:03 +0200 Subject: [PATCH 5/7] uri: Do not pass `uri_internal_t` to property handlers (#19805) * uri: Do not pass `uri_internal_t` to property handlers Within an individual property handler, the `parser` is already implicitly known, which just leaves the `->uri` field which must contain the entire state necessary for the handlers to work with. Pass the `->uri` directly. It avoids one pointer indirection, since the handlers do not need to follow the pointer to the `uri_internal_t` just to follow the pointer to the URI state. Instead the URI pointer can directly be passed using a register with the dereferences (if necessary) happening in the caller, providing more insight for the compiler to work with. It also makes it more convenient to use the handlers directly for code that already knows that it needs a specific URI parser, since no `uri_internal_t` needs to be constructed to store the already-known information about which parser to use. * uri: Use local variable for the URI in `uri_get_debug_properties()` This makes the code a little less verbose. --- ext/uri/php_uri.c | 29 +++++++------ ext/uri/php_uri_common.c | 4 +- ext/uri/php_uri_common.h | 6 +-- ext/uri/uri_parser_php_parse_url.c | 32 +++++++------- ext/uri/uri_parser_rfc3986.c | 68 +++++++++++++++--------------- ext/uri/uri_parser_rfc3986.h | 4 +- ext/uri/uri_parser_whatwg.c | 64 ++++++++++++++-------------- 7 files changed, 102 insertions(+), 105 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index f3fc05bf1b485..1af634d643b1f 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -58,42 +58,43 @@ static HashTable *uri_get_debug_properties(zend_object *object) HashTable *std_properties = zend_std_get_properties(object); HashTable *result = zend_array_dup(std_properties); - if (UNEXPECTED(internal_uri->uri == NULL)) { + const php_uri_parser * const parser = internal_uri->parser; + void * const uri = internal_uri->uri; + + if (UNEXPECTED(uri == NULL)) { return result; } - const php_uri_parser *parser = internal_uri->parser; - zval tmp; - if (parser->property_handler.scheme.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.scheme.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_SCHEME), &tmp); } - if (parser->property_handler.username.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.username.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_USERNAME), &tmp); } - if (parser->property_handler.password.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.password.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PASSWORD), &tmp); } - if (parser->property_handler.host.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.host.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_HOST), &tmp); } - if (parser->property_handler.port.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.port.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PORT), &tmp); } - if (parser->property_handler.path.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.path.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_PATH), &tmp); } - if (parser->property_handler.query.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.query.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_QUERY), &tmp); } - if (parser->property_handler.fragment.read(internal_uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { + if (parser->property_handler.fragment.read(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &tmp) == SUCCESS) { zend_hash_update(result, ZSTR_KNOWN(ZEND_STR_FRAGMENT), &tmp); } @@ -130,7 +131,7 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_get_property(const uri_interna return FAILURE; } - return property_handler->read(internal_uri, read_mode, zv); + return property_handler->read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) @@ -536,7 +537,7 @@ static void rfc3986_userinfo_read(INTERNAL_FUNCTION_PARAMETERS, php_uri_componen uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); URI_ASSERT_INITIALIZATION(internal_uri); - if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(internal_uri, read_mode, return_value) == FAILURE)) { + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_read(internal_uri->uri, read_mode, return_value) == FAILURE)) { zend_throw_error(NULL, "The userinfo component cannot be retrieved"); RETURN_THROWS(); } @@ -583,7 +584,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withUserInfo) uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); URI_ASSERT_INITIALIZATION(new_internal_uri); - if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_internal_uri, &zv, NULL) == FAILURE)) { + if (UNEXPECTED(php_uri_parser_rfc3986_userinfo_write(new_internal_uri->uri, &zv, NULL) == FAILURE)) { RETURN_THROWS(); } } diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 7bee8f46f6e02..57472ad2640b8 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -75,7 +75,7 @@ void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name prop const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); ZEND_ASSERT(property_handler != NULL); - if (UNEXPECTED(property_handler->read(internal_uri, component_read_mode, return_value) == FAILURE)) { + if (UNEXPECTED(property_handler->read(internal_uri->uri, component_read_mode, return_value) == FAILURE)) { zend_throw_error(NULL, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name))); RETURN_THROWS(); } @@ -109,7 +109,7 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, php_uri_propert zval errors; ZVAL_UNDEF(&errors); - if (UNEXPECTED(property_handler->write(new_internal_uri, property_zv, &errors) == FAILURE)) { + if (UNEXPECTED(property_handler->write(new_internal_uri->uri, property_zv, &errors) == FAILURE)) { zval_ptr_dtor(&errors); RETURN_THROWS(); } diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index a49d7f5b2445f..c56603f9a50e1 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -41,11 +41,9 @@ typedef enum php_uri_component_read_mode { PHP_URI_COMPONENT_READ_MODE_NORMALIZED_UNICODE, } php_uri_component_read_mode; -struct uri_internal_t; +typedef zend_result (*php_uri_property_handler_read)(void *uri, php_uri_component_read_mode read_mode, zval *retval); -typedef zend_result (*php_uri_property_handler_read)(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval); - -typedef zend_result (*php_uri_property_handler_write)(struct uri_internal_t *internal_uri, zval *value, zval *errors); +typedef zend_result (*php_uri_property_handler_write)(void *uri, zval *value, zval *errors); typedef enum php_uri_property_name { PHP_URI_PROPERTY_NAME_SCHEME, diff --git a/ext/uri/uri_parser_php_parse_url.c b/ext/uri/uri_parser_php_parse_url.c index 45649dcc92a7a..cab8b68a4adf8 100644 --- a/ext/uri/uri_parser_php_parse_url.c +++ b/ext/uri/uri_parser_php_parse_url.c @@ -38,9 +38,9 @@ static zend_string *decode_component(zend_string *in, php_uri_component_read_mod } } -static zend_result uri_parser_php_parse_url_scheme_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->scheme) { ZVAL_STR(retval, decode_component(parse_url_uri->scheme, read_mode)); @@ -51,9 +51,9 @@ static zend_result uri_parser_php_parse_url_scheme_read(const uri_internal_t *in return SUCCESS; } -static zend_result uri_parser_php_parse_url_username_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_username_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->user) { ZVAL_STR(retval, decode_component(parse_url_uri->user, read_mode)); @@ -64,9 +64,9 @@ static zend_result uri_parser_php_parse_url_username_read(const uri_internal_t * return SUCCESS; } -static zend_result uri_parser_php_parse_url_password_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_password_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->pass) { ZVAL_STR(retval, decode_component(parse_url_uri->pass, read_mode)); @@ -77,9 +77,9 @@ static zend_result uri_parser_php_parse_url_password_read(const uri_internal_t * return SUCCESS; } -static zend_result uri_parser_php_parse_url_host_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_host_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->host) { ZVAL_STR(retval, decode_component(parse_url_uri->host, read_mode)); @@ -90,9 +90,9 @@ static zend_result uri_parser_php_parse_url_host_read(const uri_internal_t *inte return SUCCESS; } -static zend_result uri_parser_php_parse_url_port_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_port_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->port) { ZVAL_LONG(retval, parse_url_uri->port); @@ -103,9 +103,9 @@ static zend_result uri_parser_php_parse_url_port_read(const uri_internal_t *inte return SUCCESS; } -static zend_result uri_parser_php_parse_url_path_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_path_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->path) { ZVAL_STR(retval, decode_component(parse_url_uri->path, read_mode)); @@ -116,9 +116,9 @@ static zend_result uri_parser_php_parse_url_path_read(const uri_internal_t *inte return SUCCESS; } -static zend_result uri_parser_php_parse_url_query_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_query_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->query) { ZVAL_STR(retval, decode_component(parse_url_uri->query, read_mode)); @@ -129,9 +129,9 @@ static zend_result uri_parser_php_parse_url_query_read(const uri_internal_t *int return SUCCESS; } -static zend_result uri_parser_php_parse_url_fragment_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result uri_parser_php_parse_url_fragment_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const php_url *parse_url_uri = internal_uri->uri; + const php_url *parse_url_uri = uri; if (parse_url_uri->fragment) { ZVAL_STR(retval, decode_component(parse_url_uri->fragment, read_mode)); diff --git a/ext/uri/uri_parser_rfc3986.c b/ext/uri/uri_parser_rfc3986.c index 7cb2637cb47f6..583d3b9f5e0ae 100644 --- a/ext/uri/uri_parser_rfc3986.c +++ b/ext/uri/uri_parser_rfc3986.c @@ -99,16 +99,14 @@ ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_reading(php_uri_parser_rfc398 } } -ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(uri_internal_t *internal_uri) +ZEND_ATTRIBUTE_NONNULL static UriUriA *get_uri_for_writing(php_uri_parser_rfc3986_uris *uriparser_uris) { - php_uri_parser_rfc3986_uris *uriparser_uris = internal_uri->uri; - return &uriparser_uris->uri; } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->scheme)) { ZVAL_STRINGL(retval, uriparser_uri->scheme.first, get_text_range_length(&uriparser_uri->scheme)); @@ -119,9 +117,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_scheme_read(con return SUCCESS; } -static zend_result php_uri_parser_rfc3986_scheme_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_rfc3986_scheme_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_TYPE_P(value) == IS_NULL) { @@ -143,9 +141,9 @@ static zend_result php_uri_parser_rfc3986_scheme_write(struct uri_internal_t *in } } -ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->userInfo)) { ZVAL_STRINGL(retval, uriparser_uri->userInfo.first, get_text_range_length(&uriparser_uri->userInfo)); @@ -156,9 +154,9 @@ ZEND_ATTRIBUTE_NONNULL zend_result php_uri_parser_rfc3986_userinfo_read(const ur return SUCCESS; } -zend_result php_uri_parser_rfc3986_userinfo_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +zend_result php_uri_parser_rfc3986_userinfo_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_TYPE_P(value) == IS_NULL) { @@ -183,9 +181,9 @@ zend_result php_uri_parser_rfc3986_userinfo_write(struct uri_internal_t *interna } } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_username_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_username_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->userInfo)) { size_t length = get_text_range_length(&uriparser_uri->userInfo); @@ -205,9 +203,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_username_read(c return SUCCESS; } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_password_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_password_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->userInfo)) { const char *c = memchr(uriparser_uri->userInfo.first, ':', get_text_range_length(&uriparser_uri->userInfo)); @@ -224,9 +222,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_password_read(c return SUCCESS; } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_host_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_host_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->hostText)) { if (uriparser_uri->hostData.ip6 != NULL || uriparser_uri->hostData.ipFuture.first != NULL) { @@ -248,9 +246,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_host_read(const return SUCCESS; } -static zend_result php_uri_parser_rfc3986_host_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_rfc3986_host_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_TYPE_P(value) == IS_NULL) { @@ -296,9 +294,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_long port_str_to_zend_long_checked(const char return (zend_long)result; } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_port_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_port_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->portText) && get_text_range_length(&uriparser_uri->portText) > 0) { ZVAL_LONG(retval, port_str_to_zend_long_checked(uriparser_uri->portText.first, get_text_range_length(&uriparser_uri->portText))); @@ -309,9 +307,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_port_read(const return SUCCESS; } -static zend_result php_uri_parser_rfc3986_port_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_rfc3986_port_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_TYPE_P(value) == IS_NULL) { @@ -338,9 +336,9 @@ static zend_result php_uri_parser_rfc3986_port_write(struct uri_internal_t *inte } } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_path_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_path_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (uriparser_uri->pathHead != NULL) { smart_str str = {0}; @@ -366,9 +364,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_path_read(const return SUCCESS; } -static zend_result php_uri_parser_rfc3986_path_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_rfc3986_path_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_STRLEN_P(value) == 0) { @@ -390,9 +388,9 @@ static zend_result php_uri_parser_rfc3986_path_write(struct uri_internal_t *inte } } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_query_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_query_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->query)) { ZVAL_STRINGL(retval, uriparser_uri->query.first, get_text_range_length(&uriparser_uri->query)); @@ -403,9 +401,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_query_read(cons return SUCCESS; } -static zend_result php_uri_parser_rfc3986_query_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_rfc3986_query_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_TYPE_P(value) == IS_NULL) { @@ -427,9 +425,9 @@ static zend_result php_uri_parser_rfc3986_query_write(struct uri_internal_t *int } } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_fragment_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_fragment_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const UriUriA *uriparser_uri = get_uri_for_reading(internal_uri->uri, read_mode); + const UriUriA *uriparser_uri = get_uri_for_reading(uri, read_mode); if (has_text_range(&uriparser_uri->fragment)) { ZVAL_STRINGL(retval, uriparser_uri->fragment.first, get_text_range_length(&uriparser_uri->fragment)); @@ -440,9 +438,9 @@ ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_parser_rfc3986_fragment_read(c return SUCCESS; } -static zend_result php_uri_parser_rfc3986_fragment_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_rfc3986_fragment_write(void *uri, zval *value, zval *errors) { - UriUriA *uriparser_uri = get_uri_for_writing(internal_uri); + UriUriA *uriparser_uri = get_uri_for_writing(uri); int result; if (Z_TYPE_P(value) == IS_NULL) { diff --git a/ext/uri/uri_parser_rfc3986.h b/ext/uri/uri_parser_rfc3986.h index 9b976e3d211f9..bdf792816c29f 100644 --- a/ext/uri/uri_parser_rfc3986.h +++ b/ext/uri/uri_parser_rfc3986.h @@ -28,8 +28,8 @@ typedef struct php_uri_parser_rfc3986_uris { bool normalized_uri_initialized; } php_uri_parser_rfc3986_uris; -zend_result php_uri_parser_rfc3986_userinfo_read(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval); -zend_result php_uri_parser_rfc3986_userinfo_write(struct uri_internal_t *internal_uri, zval *value, zval *errors); +zend_result php_uri_parser_rfc3986_userinfo_read(void *uri, php_uri_component_read_mode read_mode, zval *retval); +zend_result php_uri_parser_rfc3986_userinfo_write(void *uri, zval *value, zval *errors); php_uri_parser_rfc3986_uris *php_uri_parser_rfc3986_parse_ex(const char *uri_str, size_t uri_str_len, const php_uri_parser_rfc3986_uris *uriparser_base_url, bool silent); diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index 2209db0393426..70e7ccfc454be 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -247,9 +247,9 @@ static lxb_status_t serialize_to_smart_str_callback(const lxb_char_t *data, size return LXB_STATUS_OK; } -static zend_result php_uri_parser_whatwg_scheme_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_scheme_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; ZEND_ASSERT(lexbor_uri->scheme.type != LXB_URL_SCHEMEL_TYPE__UNDEF); @@ -258,9 +258,9 @@ static zend_result php_uri_parser_whatwg_scheme_read(const struct uri_internal_t return SUCCESS; } -static zend_result php_uri_parser_whatwg_scheme_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_scheme_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); @@ -274,9 +274,9 @@ static zend_result php_uri_parser_whatwg_scheme_write(struct uri_internal_t *int return SUCCESS; } -static zend_result php_uri_parser_whatwg_username_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_username_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->username.length) { ZVAL_STRINGL(retval, (const char *) lexbor_uri->username.data, lexbor_uri->username.length); @@ -287,9 +287,9 @@ static zend_result php_uri_parser_whatwg_username_read(const struct uri_internal return SUCCESS; } -static zend_result php_uri_parser_whatwg_username_write(uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_username_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); @@ -303,9 +303,9 @@ static zend_result php_uri_parser_whatwg_username_write(uri_internal_t *internal return SUCCESS; } -static zend_result php_uri_parser_whatwg_password_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_password_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->password.length > 0) { ZVAL_STRINGL(retval, (const char *) lexbor_uri->password.data, lexbor_uri->password.length); @@ -316,9 +316,9 @@ static zend_result php_uri_parser_whatwg_password_read(const struct uri_internal return SUCCESS; } -static zend_result php_uri_parser_whatwg_password_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_password_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); @@ -332,9 +332,9 @@ static zend_result php_uri_parser_whatwg_password_write(struct uri_internal_t *i return SUCCESS; } -static zend_result php_uri_parser_whatwg_host_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_host_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->host.type == LXB_URL_HOST_TYPE_IPV4) { smart_str host_str = {0}; @@ -376,9 +376,9 @@ static zend_result php_uri_parser_whatwg_host_read(const struct uri_internal_t * return SUCCESS; } -static zend_result php_uri_parser_whatwg_host_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_host_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); @@ -392,9 +392,9 @@ static zend_result php_uri_parser_whatwg_host_write(struct uri_internal_t *inter return SUCCESS; } -static zend_result php_uri_parser_whatwg_port_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_port_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->has_port) { ZVAL_LONG(retval, lexbor_uri->port); @@ -405,9 +405,9 @@ static zend_result php_uri_parser_whatwg_port_read(const struct uri_internal_t * return SUCCESS; } -static zend_result php_uri_parser_whatwg_port_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_port_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_long_or_null_to_lexbor_str(value, &str); @@ -421,9 +421,9 @@ static zend_result php_uri_parser_whatwg_port_write(struct uri_internal_t *inter return SUCCESS; } -static zend_result php_uri_parser_whatwg_path_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_path_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->path.str.length) { ZVAL_STRINGL(retval, (const char *) lexbor_uri->path.str.data, lexbor_uri->path.str.length); @@ -434,9 +434,9 @@ static zend_result php_uri_parser_whatwg_path_read(const struct uri_internal_t * return SUCCESS; } -static zend_result php_uri_parser_whatwg_path_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_path_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); @@ -450,9 +450,9 @@ static zend_result php_uri_parser_whatwg_path_write(struct uri_internal_t *inter return SUCCESS; } -static zend_result php_uri_parser_whatwg_query_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_query_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->query.length) { ZVAL_STRINGL(retval, (const char *) lexbor_uri->query.data, lexbor_uri->query.length); @@ -463,9 +463,9 @@ static zend_result php_uri_parser_whatwg_query_read(const struct uri_internal_t return SUCCESS; } -static zend_result php_uri_parser_whatwg_query_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_query_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); @@ -479,9 +479,9 @@ static zend_result php_uri_parser_whatwg_query_write(struct uri_internal_t *inte return SUCCESS; } -static zend_result php_uri_parser_whatwg_fragment_read(const struct uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *retval) +static zend_result php_uri_parser_whatwg_fragment_read(void *uri, php_uri_component_read_mode read_mode, zval *retval) { - const lxb_url_t *lexbor_uri = internal_uri->uri; + const lxb_url_t *lexbor_uri = uri; if (lexbor_uri->fragment.length) { ZVAL_STRINGL(retval, (const char *) lexbor_uri->fragment.data, lexbor_uri->fragment.length); @@ -492,9 +492,9 @@ static zend_result php_uri_parser_whatwg_fragment_read(const struct uri_internal return SUCCESS; } -static zend_result php_uri_parser_whatwg_fragment_write(struct uri_internal_t *internal_uri, zval *value, zval *errors) +static zend_result php_uri_parser_whatwg_fragment_write(void *uri, zval *value, zval *errors) { - lxb_url_t *lexbor_uri = internal_uri->uri; + lxb_url_t *lexbor_uri = uri; lexbor_str_t str = {0}; zval_string_or_null_to_lexbor_str(value, &str); From bd4e2c78acf18ddf0b2b9a6e76e25b72587fb18a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Thu, 11 Sep 2025 22:36:26 +0200 Subject: [PATCH 6/7] Fix fuzzer runner (#19676) --- sapi/fuzzer/fuzzer-execute-common.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sapi/fuzzer/fuzzer-execute-common.h b/sapi/fuzzer/fuzzer-execute-common.h index 20fcad111cd6b..338c771e551a3 100644 --- a/sapi/fuzzer/fuzzer-execute-common.h +++ b/sapi/fuzzer/fuzzer-execute-common.h @@ -23,6 +23,7 @@ #include "fuzzer.h" #include "fuzzer-sapi.h" #include "zend_exceptions.h" +#include "zend_vm.h" #define FILE_NAME "/tmp/fuzzer.php" #define MAX_STEPS 1000 @@ -32,10 +33,6 @@ static uint32_t steps_left; static bool bailed_out = false; -/* Because the fuzzer is always compiled with clang, - * we can assume that we don't use global registers / hybrid VM. */ -typedef zend_op *(ZEND_FASTCALL *opcode_handler_t)(zend_execute_data *, const zend_op *); - static zend_always_inline void fuzzer_bailout(void) { bailed_out = true; zend_bailout(); @@ -67,7 +64,7 @@ static void fuzzer_execute_ex(zend_execute_data *execute_data) { while (1) { fuzzer_step(); - opline = ((opcode_handler_t) opline->handler)(execute_data, opline); + opline = ((zend_vm_opcode_handler_func_t) zend_get_opcode_handler_func(opline))(execute_data, opline); if ((uintptr_t) opline & ZEND_VM_ENTER_BIT) { opline = (const zend_op *) ((uintptr_t) opline & ~ZEND_VM_ENTER_BIT); if (opline) { From 3e9caf5338a41771d4f93f926db501366d9d7321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Thu, 11 Sep 2025 23:05:07 +0200 Subject: [PATCH 7/7] uri: Optimize `php_uri_get_*()` (#19807) * uri: Do not check the return value of `uri_property_handler_from_internal_uri()` It's impossible for this function to return `NULL`, since it will always return a positive offset into a struct. * uri: Optimize `php_uri_get_*()` Currently the `php_uri_get_*()` functions call into `php_uri_get_property()` with a constant `php_uri_property_name`. This name will then be used to look up the correct property handler by a function in a different compilation unit. Improve this by making `uri_property_handler_from_internal_uri` take a `php_uri_parser` rather than a `uri_internal_t`, defining it in a header as inlinable (and renaming it to better match its updated purpose). This allows the compiler to fully inline `php_uri_get_property()`, such that no dynamic lookups will need to happen. * uri: Eliminate `php_uri_get_property()` entirely Spelling out the effective implementation explicitly is not much longer than going through `php_uri_get_property()`, but much more explicit in what is happening. --- ext/uri/php_uri.c | 26 ++++++++------------------ ext/uri/php_uri_common.c | 29 ++--------------------------- ext/uri/php_uri_common.h | 24 +++++++++++++++++++++++- 3 files changed, 33 insertions(+), 46 deletions(-) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 1af634d643b1f..a09a93dbc0365 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -124,54 +124,44 @@ ZEND_ATTRIBUTE_NONNULL PHPAPI uri_internal_t *php_uri_parse(const php_uri_parser return internal_uri; } -ZEND_ATTRIBUTE_NONNULL static zend_result php_uri_get_property(const uri_internal_t *internal_uri, php_uri_property_name property_name, php_uri_component_read_mode read_mode, zval *zv) -{ - const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - if (property_handler == NULL) { - return FAILURE; - } - - return property_handler->read(internal_uri->uri, read_mode, zv); -} - ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_scheme(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_SCHEME, read_mode, zv); + return internal_uri->parser->property_handler.scheme.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_username(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_USERNAME, read_mode, zv); + return internal_uri->parser->property_handler.username.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_password(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_PASSWORD, read_mode, zv); + return internal_uri->parser->property_handler.password.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_host(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_HOST, read_mode, zv); + return internal_uri->parser->property_handler.host.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_port(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_PORT, read_mode, zv); + return internal_uri->parser->property_handler.port.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_path(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_PATH, read_mode, zv); + return internal_uri->parser->property_handler.path.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_query(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_QUERY, read_mode, zv); + return internal_uri->parser->property_handler.query.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI zend_result php_uri_get_fragment(const uri_internal_t *internal_uri, php_uri_component_read_mode read_mode, zval *zv) { - return php_uri_get_property(internal_uri, PHP_URI_PROPERTY_NAME_FRAGMENT, read_mode, zv); + return internal_uri->parser->property_handler.fragment.read(internal_uri->uri, read_mode, zv); } ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_free(uri_internal_t *internal_uri) diff --git a/ext/uri/php_uri_common.c b/ext/uri/php_uri_common.c index 57472ad2640b8..efb7688a94502 100644 --- a/ext/uri/php_uri_common.c +++ b/ext/uri/php_uri_common.c @@ -19,29 +19,6 @@ #include "Zend/zend_exceptions.h" #include "php_uri_common.h" -const php_uri_property_handler *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, php_uri_property_name property_name) -{ - switch (property_name) { - case PHP_URI_PROPERTY_NAME_SCHEME: - return &internal_uri->parser->property_handler.scheme; - case PHP_URI_PROPERTY_NAME_USERNAME: - return &internal_uri->parser->property_handler.username; - case PHP_URI_PROPERTY_NAME_PASSWORD: - return &internal_uri->parser->property_handler.password; - case PHP_URI_PROPERTY_NAME_HOST: - return &internal_uri->parser->property_handler.host; - case PHP_URI_PROPERTY_NAME_PORT: - return &internal_uri->parser->property_handler.port; - case PHP_URI_PROPERTY_NAME_PATH: - return &internal_uri->parser->property_handler.path; - case PHP_URI_PROPERTY_NAME_QUERY: - return &internal_uri->parser->property_handler.query; - case PHP_URI_PROPERTY_NAME_FRAGMENT: - return &internal_uri->parser->property_handler.fragment; - EMPTY_SWITCH_DEFAULT_CASE() - } -} - static zend_string *get_known_string_by_property_name(php_uri_property_name property_name) { switch (property_name) { @@ -72,8 +49,7 @@ void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name prop uri_internal_t *internal_uri = Z_URI_INTERNAL_P(ZEND_THIS); URI_ASSERT_INITIALIZATION(internal_uri); - const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - ZEND_ASSERT(property_handler != NULL); + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); if (UNEXPECTED(property_handler->read(internal_uri->uri, component_read_mode, return_value) == FAILURE)) { zend_throw_error(NULL, "The %s component cannot be retrieved", ZSTR_VAL(get_known_string_by_property_name(property_name))); @@ -96,8 +72,7 @@ static void uri_write_component_ex(INTERNAL_FUNCTION_PARAMETERS, php_uri_propert * case of an exception being thrown. */ RETVAL_OBJ(new_object); - const php_uri_property_handler *property_handler = uri_property_handler_from_internal_uri(internal_uri, property_name); - ZEND_ASSERT(property_handler != NULL); + const php_uri_property_handler *property_handler = php_uri_parser_property_handler_by_name(internal_uri->parser, property_name); uri_internal_t *new_internal_uri = uri_internal_from_obj(new_object); URI_ASSERT_INITIALIZATION(new_internal_uri); diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index c56603f9a50e1..f061db6f981b1 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -166,7 +166,29 @@ PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object); #define PHP_URI_PARSER_PHP_PARSE_URL "parse_url" #define URI_SERIALIZED_PROPERTY_NAME "uri" -const php_uri_property_handler *uri_property_handler_from_internal_uri(const uri_internal_t *internal_uri, php_uri_property_name property_name); +static inline const php_uri_property_handler *php_uri_parser_property_handler_by_name(const php_uri_parser *parser, php_uri_property_name property_name) +{ + switch (property_name) { + case PHP_URI_PROPERTY_NAME_SCHEME: + return &parser->property_handler.scheme; + case PHP_URI_PROPERTY_NAME_USERNAME: + return &parser->property_handler.username; + case PHP_URI_PROPERTY_NAME_PASSWORD: + return &parser->property_handler.password; + case PHP_URI_PROPERTY_NAME_HOST: + return &parser->property_handler.host; + case PHP_URI_PROPERTY_NAME_PORT: + return &parser->property_handler.port; + case PHP_URI_PROPERTY_NAME_PATH: + return &parser->property_handler.path; + case PHP_URI_PROPERTY_NAME_QUERY: + return &parser->property_handler.query; + case PHP_URI_PROPERTY_NAME_FRAGMENT: + return &parser->property_handler.fragment; + EMPTY_SWITCH_DEFAULT_CASE() + } +} + void uri_read_component(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name, php_uri_component_read_mode component_read_mode); void uri_write_component_str(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name); void uri_write_component_str_or_null(INTERNAL_FUNCTION_PARAMETERS, php_uri_property_name property_name);