diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index e8433e7c4f67..a4f2a55630e4 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -1159,8 +1159,10 @@ int make_http_soap_request( zend_string_release_ex(http_body, 0); if (new_uri->scheme == NULL && new_uri->path != NULL) { 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->host == 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 (uri->path) { char *t = ZSTR_VAL(uri->path); diff --git a/ext/soap/tests/bugs/protocol_relative_redirect.phpt b/ext/soap/tests/bugs/protocol_relative_redirect.phpt new file mode 100644 index 000000000000..e8f30ca66872 --- /dev/null +++ b/ext/soap/tests/bugs/protocol_relative_redirect.phpt @@ -0,0 +1,49 @@ +--TEST-- +SOAP client follows a protocol-relative (//host/path) redirect Location without leaking the host +--EXTENSIONS-- +soap +--SKIPIF-- + +--FILE-- +', + '', + 'ok', + ''; +} else { + http_response_code(302); + header("Location: //" . $_SERVER["HTTP_HOST"] . "/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