Skip to content

Commit 39e7411

Browse files
committed
soap: do not overwrite the parsed host on a protocol-relative redirect
When a redirect Location is a protocol-relative reference (//host/path), php_url_parse() already fills new_url->host, but the scheme-less redirect handling overwrote it with a copy of the request host without releasing the parsed one. That leaks a zend_string per such redirect and pins the redirect back to the original host instead of the one the server named. Inherit host and port from the request URL only when new_url->host is NULL, mirroring the scheme guard directly above.
1 parent 6a323eb commit 39e7411

2 files changed

Lines changed: 53 additions & 2 deletions

File tree

ext/soap/php_http.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,8 +1151,10 @@ int make_http_soap_request(zval *this_ptr,
11511151
zend_string_release_ex(http_body, 0);
11521152
if (new_url->scheme == NULL && new_url->path != NULL) {
11531153
new_url->scheme = phpurl->scheme ? zend_string_copy(phpurl->scheme) : NULL;
1154-
new_url->host = phpurl->host ? zend_string_copy(phpurl->host) : NULL;
1155-
new_url->port = phpurl->port;
1154+
if (new_url->host == NULL) {
1155+
new_url->host = phpurl->host ? zend_string_copy(phpurl->host) : NULL;
1156+
new_url->port = phpurl->port;
1157+
}
11561158
if (new_url->path && ZSTR_VAL(new_url->path)[0] != '/') {
11571159
if (phpurl->path) {
11581160
char *t = ZSTR_VAL(phpurl->path);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
SOAP client follows a protocol-relative (//host/path) redirect Location without leaking the host
3+
--EXTENSIONS--
4+
soap
5+
--SKIPIF--
6+
<?php
7+
if (!file_exists(__DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc")) {
8+
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
include __DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc";
14+
15+
$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX];
16+
if (php_ini_loaded_file()) {
17+
$args[] = "-c";
18+
$args[] = php_ini_loaded_file();
19+
}
20+
21+
$code = <<<'PHP'
22+
if ($_SERVER["REQUEST_URI"] === "/redirected") {
23+
header("Content-Type: text/xml; charset=utf-8");
24+
echo '<?xml version="1.0" encoding="UTF-8"?>',
25+
'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">',
26+
'<SOAP-ENV:Body><fooResponse><result>ok</result></fooResponse></SOAP-ENV:Body>',
27+
'</SOAP-ENV:Envelope>';
28+
} else {
29+
http_response_code(302);
30+
header("Location: //" . $_SERVER["HTTP_HOST"] . "/redirected");
31+
}
32+
PHP;
33+
34+
php_cli_server_start($code, null, $args);
35+
36+
$client = new SoapClient(null, [
37+
'location' => 'http://' . PHP_CLI_SERVER_ADDRESS . '/start',
38+
'uri' => 'test-uri',
39+
]);
40+
41+
try {
42+
$client->__soapCall("foo", []);
43+
echo "redirect followed\n";
44+
} catch (SoapFault $e) {
45+
echo "SoapFault: " . $e->getMessage() . "\n";
46+
}
47+
?>
48+
--EXPECT--
49+
redirect followed

0 commit comments

Comments
 (0)