From 7477efc4ff8bbd8bbfe652836936bd8d958d852b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 9 Mar 2026 22:03:31 +0000 Subject: [PATCH 1/3] ext/soap: Add test for Set-Cookie option parsing bug. The cookie option parser uses a wrong offset to start scanning attributes, causing cookie values containing substrings like "path=" or "domain=" to be falsely matched as attributes. --- .../bugs/cookie_parse_options_offset.phpt | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 ext/soap/tests/bugs/cookie_parse_options_offset.phpt diff --git a/ext/soap/tests/bugs/cookie_parse_options_offset.phpt b/ext/soap/tests/bugs/cookie_parse_options_offset.phpt new file mode 100644 index 0000000000000..988af9d31959f --- /dev/null +++ b/ext/soap/tests/bugs/cookie_parse_options_offset.phpt @@ -0,0 +1,61 @@ +--TEST-- +SOAP Set-Cookie option parsing starts at wrong offset due to variable shadowing +--EXTENSIONS-- +soap +--SKIPIF-- + +--FILE-- + + + + + + +XML; +PHP; + +php_cli_server_start($code, null, $args); + +$client = new SoapClient(null, [ + 'location' => 'http://' . PHP_CLI_SERVER_ADDRESS . '/test/endpoint', + 'uri' => 'test-uri', + 'trace' => true, +]); + +try { + $client->__soapCall("test", []); +} catch (SoapFault $e) { + // Response parsing may fault, cookies are still stored +} + +$cookies = $client->__getCookies(); + +// path should default to "/test" from the request URI, not "/evil" from the value. +echo "value: " . $cookies['sessionkey'][0] . "\n"; +echo "path: " . $cookies['sessionkey'][1] . "\n"; +echo "domain: " . $cookies['sessionkey'][2] . "\n"; +?> +--EXPECT-- +value: path=/evil +path: /test +domain: good.com From a1dd4bab5488faaf1f689cfaa9047593e800339f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 9 Mar 2026 22:20:01 +0000 Subject: [PATCH 2/3] - remove unneeded shadowed var. - fix wrong cookie options offset calculation, using separator offset instead. --- ext/soap/php_http.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 2db45fe49b105..c7fd6496841ce 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -1010,7 +1010,6 @@ int make_http_soap_request(zval *this_ptr, char *sempos = strstr(cookie, ";"); if (eqpos != NULL && (sempos == NULL || sempos > eqpos)) { smart_str name = {0}; - int cookie_len; zval zcookie; if (sempos != NULL) { @@ -1026,7 +1025,7 @@ int make_http_soap_request(zval *this_ptr, add_index_stringl(&zcookie, 0, eqpos + 1, cookie_len); if (sempos != NULL) { - char *options = cookie + cookie_len+1; + char *options = sempos + 1; while (*options) { while (*options == ' ') {options++;} sempos = strstr(options, ";"); From f3698fa18bd98912c1b4e55191a2742a9271d755 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 10 Mar 2026 19:47:39 +0000 Subject: [PATCH 3/3] review --- ext/soap/php_http.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index c7fd6496841ce..0bec42afbc37c 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -1011,18 +1011,19 @@ int make_http_soap_request(zval *this_ptr, if (eqpos != NULL && (sempos == NULL || sempos > eqpos)) { smart_str name = {0}; zval zcookie; + size_t cookie_value_len; if (sempos != NULL) { - cookie_len = sempos-(eqpos+1); + cookie_value_len = sempos-(eqpos+1); } else { - cookie_len = strlen(cookie)-(eqpos-cookie)-1; + cookie_value_len = strlen(cookie)-(eqpos-cookie)-1; } smart_str_appendl(&name, cookie, eqpos - cookie); smart_str_0(&name); array_init(&zcookie); - add_index_stringl(&zcookie, 0, eqpos + 1, cookie_len); + add_index_stringl(&zcookie, 0, eqpos + 1, cookie_value_len); if (sempos != NULL) { char *options = sempos + 1;