[php-src] PHP-8.5: ext/soap: fix NULL deref on malformed HTTP status line
Ilia Alshanetsky <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Date: 2026-07-16T21:58:20-04:00
Commit: https://github.com/php/php-src/commit/1c4bf04783b4915a908a1f7f09a4f4fe2f115ed6
Raw diff: https://github.com/php/php-src/commit/1c4bf04783b4915a908a1f7f09a4f4fe2f115ed6.diff
ext/soap: fix NULL deref on malformed HTTP status line
make_http_soap_request() looked for the reason phrase with strstr(tmp, " ")
even when the first strstr() found no space, which happens for a status line
carrying a version but no status code, such as "HTTP/1.1". tmp is NULL there,
so strstr() dereferenced it and the client crashed.
Only parse the reason phrase when a status code field was present.
Closes GH-22761
Changed paths:
A ext/soap/tests/http_status_line_no_code.phpt
M ext/soap/php_http.c
Diff:
diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c
index e9fd68007d26..125c92582008 100644
--- a/ext/soap/php_http.c
+++ b/ext/soap/php_http.c
@@ -956,14 +956,14 @@ int make_http_soap_request(zval *this_ptr,
if (tmp != NULL) {
tmp++;
http_status = atoi(tmp);
- }
- tmp = strstr(tmp," ");
- if (tmp != NULL) {
- tmp++;
- if (http_msg) {
- efree(http_msg);
+ tmp = strstr(tmp," ");
+ if (tmp != NULL) {
+ tmp++;
+ if (http_msg) {
+ efree(http_msg);
+ }
+ http_msg = estrdup(tmp);
}
- http_msg = estrdup(tmp);
}
efree(http_version);
diff --git a/ext/soap/tests/http_status_line_no_code.phpt b/ext/soap/tests/http_status_line_no_code.phpt
new file mode 100644
index 000000000000..de943571a492
--- /dev/null
+++ b/ext/soap/tests/http_status_line_no_code.phpt
@@ -0,0 +1,33 @@
+--TEST--
+SoapClient: malformed HTTP status line without status code must not crash
+--EXTENSIONS--
+soap
+--FILE--
+<?php
+$serverCode = <<<'CODE'
+$server = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr);
+phpt_notify_server_start($server);
+$conn = stream_socket_accept($server);
+while (($line = fgets($conn)) !== false) {
+ if ($line === "\r\n" || $line === "\n") {
+ break;
+ }
+}
+fwrite($conn, "HTTP/1.1\r\nContent-Type: text/xml\r\nContent-Length: 0\r\n\r\n");
+fclose($conn);
+CODE;
+
+$clientCode = <<<'CODE'
+$client = new SoapClient(null, [
+ 'location' => 'http://{{ ADDR }}',
+ 'uri' => 'http://testuri.org',
+ 'connection_timeout' => 3,
+]);
+var_dump($client->__doRequest('<x/>', 'http://{{ ADDR }}', 'T', 1));
+CODE;
+
+include sprintf('%s/../../openssl/tests/ServerClientTestCase.inc', __DIR__);
+ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
+?>
+--EXPECT--
+string(0) ""