Skip to content

Commit 1b1677a

Browse files
committed
Fix bug #76232: SoapClient Cookie Header Semicolon
According to RFC 6265 [1] the cookies must be separated by "; " not ";", and it must not end with ";". [1] https://datatracker.ietf.org/doc/html/rfc6265 Closes GH-14406.
1 parent 4767061 commit 1b1677a

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ PHP NEWS
3737
. Fix memory leaks with string function name lookups. (nielsdos)
3838
. Fixed bug #69280 (SoapClient classmap doesn't support fully qualified class
3939
name). (nielsdos)
40+
. Fixed bug #76232 (SoapClient Cookie Header Semicolon). (nielsdos)
4041

4142
- Sodium:
4243
. Fix memory leaks in ext/sodium on failure of some functions. (nielsdos)

ext/soap/php_http.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,7 @@ int make_http_soap_request(zval *this_ptr,
833833
zval *data;
834834
zend_string *key;
835835
has_cookies = 1;
836+
bool first_cookie = true;
836837
smart_str_append_const(&soap_headers, "Cookie: ");
837838
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(cookies), key, data) {
838839
if (key && Z_TYPE_P(data) == IS_ARRAY) {
@@ -848,10 +849,13 @@ int make_http_soap_request(zval *this_ptr,
848849
Z_TYPE_P(tmp) != IS_STRING ||
849850
in_domain(ZSTR_VAL(phpurl->host),Z_STRVAL_P(tmp))) &&
850851
(use_ssl || (tmp = zend_hash_index_find(Z_ARRVAL_P(data), 3)) == NULL)) {
852+
if (!first_cookie) {
853+
smart_str_appends(&soap_headers, "; ");
854+
}
855+
first_cookie = false;
851856
smart_str_append(&soap_headers, key);
852857
smart_str_appendc(&soap_headers, '=');
853858
smart_str_append(&soap_headers, Z_STR_P(value));
854-
smart_str_appendc(&soap_headers, ';');
855859
}
856860
}
857861
}

ext/soap/tests/bugs/bug76232.phpt

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
--TEST--
2+
Bug #76232 (SoapClient Cookie Header Semicolon)
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+
14+
include __DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc";
15+
16+
$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX];
17+
if (php_ini_loaded_file()) {
18+
// Necessary such that it works from a development directory in which case extension_dir might not be the real extension dir
19+
$args[] = "-c";
20+
$args[] = php_ini_loaded_file();
21+
}
22+
$code = <<<'PHP'
23+
/* Receive */
24+
$content = trim(file_get_contents("php://input")) . PHP_EOL;
25+
PHP;
26+
27+
php_cli_server_start($code, null, $args);
28+
29+
$client = new soapclient(NULL, [
30+
'location' => 'http://' . PHP_CLI_SERVER_ADDRESS,
31+
'uri' => 'misc-uri',
32+
'trace' => true,
33+
]);
34+
35+
echo "=== Request with one cookie ===\n";
36+
37+
$client->__setCookie('testcookie1', 'true');
38+
$client->__soapCall("foo", []);
39+
echo $client->__getLastRequestHeaders();
40+
41+
echo "=== Request with two cookies ===\n";
42+
43+
$client->__setCookie('testcookie2', 'true');
44+
$client->__soapCall("foo", []);
45+
46+
echo $client->__getLastRequestHeaders();
47+
?>
48+
--EXPECTF--
49+
=== Request with one cookie ===
50+
POST / HTTP/1.1
51+
Host: %s
52+
Connection: Keep-Alive
53+
User-Agent: PHP-SOAP/%s
54+
Content-Type: text/xml; charset=utf-8
55+
SOAPAction: "misc-uri#foo"
56+
Content-Length: %d
57+
Cookie: testcookie1=true
58+
59+
=== Request with two cookies ===
60+
POST / HTTP/1.1
61+
Host: %s
62+
Connection: Keep-Alive
63+
User-Agent: PHP-SOAP/%s
64+
Content-Type: text/xml; charset=utf-8
65+
SOAPAction: "misc-uri#foo"
66+
Content-Length: %d
67+
Cookie: testcookie1=true; testcookie2=true

0 commit comments

Comments
 (0)