From a480965c90b4f4948f211c8b139788371e031838 Mon Sep 17 00:00:00 2001 From: Weilin Du Date: Wed, 17 Jun 2026 04:48:17 +0800 Subject: [PATCH 1/2] ext/opcache: unwrap reference wrappers in typed by-value returns (#21973) --- NEWS | 2 ++ Zend/zend_vm_def.h | 5 +++- Zend/zend_vm_execute.h | 25 +++++++++++++++---- ext/opcache/tests/opt/gh21972.phpt | 39 ++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 ext/opcache/tests/opt/gh21972.phpt diff --git a/NEWS b/NEWS index 05bdd1b35ff7..afb45fca45ca 100644 --- a/NEWS +++ b/NEWS @@ -93,6 +93,8 @@ PHP NEWS . Fix persistent free of non-persistent connect_attr key (David Carlier). - Opcache: + . Fixed bug GH-21972 (Corrupted variable type when a typed by-value return + contains a reference wrapper). (Weilin Du) . Fixed tracing JIT crash when a VM interrupt is handled during an observed user function call. (Levi Morrison) . Fixed bug GH-22004 (Assertion failure at ext/opcache/jit/zend_jit_trace.c). diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 34906e1bfcca..c46b17101546 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4387,7 +4387,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV ZVAL_DEREF(retval_ptr); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ref)))) { ZEND_VM_NEXT_OPCODE(); } @@ -4417,6 +4417,9 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV } retval_ptr = retval_ref; } + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } } SAVE_OPLINE(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d4b2aff1907b..f4f35ce2a8a9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -10772,7 +10772,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP ZVAL_DEREF(retval_ptr); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ref)))) { ZEND_VM_NEXT_OPCODE(); } @@ -10802,6 +10802,9 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYP } retval_ptr = retval_ref; } + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } } SAVE_OPLINE(); @@ -21517,7 +21520,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN ZVAL_DEREF(retval_ptr); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ref)))) { ZEND_VM_NEXT_OPCODE(); } @@ -21547,6 +21550,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN } retval_ptr = retval_ref; } + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } } SAVE_OPLINE(); @@ -30016,7 +30022,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN ZVAL_DEREF(retval_ptr); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ref)))) { ZEND_VM_NEXT_OPCODE(); } @@ -30046,6 +30052,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN } retval_ptr = retval_ref; } + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } } SAVE_OPLINE(); @@ -37830,7 +37839,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED ZVAL_DEREF(retval_ptr); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ref)))) { ZEND_VM_NEXT_OPCODE(); } @@ -37860,6 +37869,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED } retval_ptr = retval_ref; } + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } } SAVE_OPLINE(); @@ -50642,7 +50654,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU ZVAL_DEREF(retval_ptr); } - if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ref)))) { ZEND_VM_NEXT_OPCODE(); } @@ -50672,6 +50684,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU } retval_ptr = retval_ref; } + if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) { + ZEND_VM_NEXT_OPCODE(); + } } SAVE_OPLINE(); diff --git a/ext/opcache/tests/opt/gh21972.phpt b/ext/opcache/tests/opt/gh21972.phpt new file mode 100644 index 000000000000..f34f9b45ccf2 --- /dev/null +++ b/ext/opcache/tests/opt/gh21972.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-21972: Typed by-value return must not leak reference wrapper +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.optimization_level=-1 +--EXTENSIONS-- +opcache +--FILE-- + +--EXPECT-- +string(6) "string" +string(5) "false" +string(5) "false" From ef896b26d4b935ffd081366e462327156e22d601 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Tue, 16 Jun 2026 15:52:00 -0400 Subject: [PATCH 2/2] Fix SOAP client failing to follow a scheme-less redirect Location The HTTP redirect handler inherited scheme, host and port from the newly parsed Location URI itself instead of the previous request URI, so a scheme-less (relative or absolute-path) Location left the host NULL and the retry aborted with "Unable to parse URL". Read the inherited components and the path base from the request URI, restoring the behaviour the URI-parser refactor changed. Closes GH-22341 --- ext/soap/php_http.c | 10 ++--- ext/soap/tests/bugs/relative_redirect.phpt | 49 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 ext/soap/tests/bugs/relative_redirect.phpt diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 944b033363c6..c7f3732f2987 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -1162,12 +1162,12 @@ int make_http_soap_request( zend_string_release_ex(http_headers, 0); zend_string_release_ex(http_body, 0); if (new_uri->scheme == NULL && new_uri->path != NULL) { - new_uri->scheme = new_uri->scheme ? zend_string_copy(new_uri->scheme) : NULL; - new_uri->host = new_uri->host ? zend_string_copy(new_uri->host) : NULL; - new_uri->port = new_uri->port; + new_uri->scheme = uri->scheme ? zend_string_copy(uri->scheme) : NULL; + new_uri->host = uri->host ? zend_string_copy(uri->host) : NULL; + new_uri->port = uri->port; if (new_uri->path && ZSTR_VAL(new_uri->path)[0] != '/') { - if (new_uri->path) { - char *t = ZSTR_VAL(new_uri->path); + if (uri->path) { + char *t = ZSTR_VAL(uri->path); char *p = strrchr(t, '/'); if (p) { zend_string *s = zend_string_alloc((p - t) + ZSTR_LEN(new_uri->path) + 2, 0); diff --git a/ext/soap/tests/bugs/relative_redirect.phpt b/ext/soap/tests/bugs/relative_redirect.phpt new file mode 100644 index 000000000000..774e7cbd98d7 --- /dev/null +++ b/ext/soap/tests/bugs/relative_redirect.phpt @@ -0,0 +1,49 @@ +--TEST-- +SOAP client follows a redirect with a scheme-less (relative) Location +--EXTENSIONS-- +soap +--SKIPIF-- + +--FILE-- +', + '', + 'ok', + ''; +} else { + http_response_code(302); + header("Location: /redirected"); +} +PHP; + +php_cli_server_start($code, null, $args); + +$client = new SoapClient(null, [ + 'location' => 'http://' . PHP_CLI_SERVER_ADDRESS . '/start', + 'uri' => 'test-uri', +]); + +try { + $client->__soapCall("foo", []); + echo "redirect followed\n"; +} catch (SoapFault $e) { + echo "SoapFault: " . $e->getMessage() . "\n"; +} +?> +--EXPECT-- +redirect followed