diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 0bec42afbc37..e9fd68007d26 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -1151,8 +1151,10 @@ int make_http_soap_request(zval *this_ptr, zend_string_release_ex(http_body, 0); if (new_url->scheme == NULL && new_url->path != NULL) { new_url->scheme = phpurl->scheme ? zend_string_copy(phpurl->scheme) : NULL; - new_url->host = phpurl->host ? zend_string_copy(phpurl->host) : NULL; - new_url->port = phpurl->port; + if (new_url->host == NULL) { + new_url->host = phpurl->host ? zend_string_copy(phpurl->host) : NULL; + new_url->port = phpurl->port; + } if (new_url->path && ZSTR_VAL(new_url->path)[0] != '/') { if (phpurl->path) { char *t = ZSTR_VAL(phpurl->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