diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 4253037fda52..1b28ce25fe37 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -4327,8 +4327,15 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *ca } \ } while (0) +#if ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +# define ZEND_VM_KIND_TAILCALL_SAVE_OPLINE() SAVE_OPLINE() +#else +# define ZEND_VM_KIND_TAILCALL_SAVE_OPLINE() +#endif + #define ZEND_VM_LOOP_INTERRUPT_CHECK() do { \ if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \ + ZEND_VM_KIND_TAILCALL_SAVE_OPLINE(); \ ZEND_VM_LOOP_INTERRUPT(); \ } \ } while (0) diff --git a/ext/uri/tests/whatwg/modification/multiple_error_with_warnings.phpt b/ext/uri/tests/whatwg/modification/multiple_error_with_warnings.phpt new file mode 100644 index 000000000000..b5dd89446601 --- /dev/null +++ b/ext/uri/tests/whatwg/modification/multiple_error_with_warnings.phpt @@ -0,0 +1,23 @@ +--TEST-- +Test Uri\WhatWg\Url component modification - error - modifying multiple components with warnings before throwing an exception +--FILE-- +withScheme("\tscheme") + ->withHost("\tex.com") + ->withQuery("\refoo=bar") + ->withFragment("\nfoo"); + +try { + $url->withScheme("0"); +} catch (Throwable $e) { + echo $e::class, ": ", $e->getMessage(), PHP_EOL; + var_dump($e->errors); +} + +?> +--EXPECT-- +Uri\WhatWg\InvalidUrlException: The specified scheme is malformed +array(0) { +} diff --git a/ext/uri/uri_parser_whatwg.c b/ext/uri/uri_parser_whatwg.c index f4e148704004..c4781b0b50d9 100644 --- a/ext/uri/uri_parser_whatwg.c +++ b/ext/uri/uri_parser_whatwg.c @@ -264,6 +264,8 @@ static zend_result php_uri_parser_whatwg_scheme_write(void *uri, zval *value, zv zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_protocol_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "scheme"); @@ -304,6 +306,8 @@ static zend_result php_uri_parser_whatwg_username_write(void *uri, zval *value, zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_username_set(lexbor_uri, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "username"); @@ -333,6 +337,8 @@ static zend_result php_uri_parser_whatwg_password_write(void *uri, zval *value, zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_password_set(lexbor_uri, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "password"); @@ -418,6 +424,8 @@ static zend_result php_uri_parser_whatwg_host_write(void *uri, zval *value, zval zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_hostname_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "host"); @@ -447,6 +455,8 @@ static zend_result php_uri_parser_whatwg_port_write(void *uri, zval *value, zval zval_long_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_port_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "port"); @@ -476,6 +486,8 @@ static zend_result php_uri_parser_whatwg_path_write(void *uri, zval *value, zval zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_pathname_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "path"); @@ -505,6 +517,8 @@ static zend_result php_uri_parser_whatwg_query_write(void *uri, zval *value, zva zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_search_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "query string"); @@ -534,6 +548,8 @@ static zend_result php_uri_parser_whatwg_fragment_write(void *uri, zval *value, zval_string_or_null_to_lexbor_str(value, &str); + lxb_url_parser_clean(&lexbor_parser); + if (lxb_url_api_hash_set(lexbor_uri, &lexbor_parser, str.data, str.length) != LXB_STATUS_OK) { throw_invalid_url_exception_during_write(errors, "fragment"); diff --git a/ext/zend_test/tests/observer_vm_interrupt_tailcall_return.phpt b/ext/zend_test/tests/observer_vm_interrupt_tailcall_return.phpt new file mode 100644 index 000000000000..95af2681c253 --- /dev/null +++ b/ext/zend_test/tests/observer_vm_interrupt_tailcall_return.phpt @@ -0,0 +1,29 @@ +--TEST-- +Observer: VM interrupt during tailcall return to caller +--DESCRIPTION-- +This exercises a VM interrupt raised immediately before a user function returns +to a caller that invoked it through DO_FCALL. On the tailcall VM, the caller's +saved opline must point to the opcode after DO_FCALL before a pending interrupt +is handled. +--EXTENSIONS-- +zend_test +--INI-- +opcache.jit=0 +zend_test.observer.set_vm_interrupt_on_begin=1 +--FILE-- + +--EXPECT-- +ok