Skip to content

Commit 1c4bf04

Browse files
committed
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
1 parent 0549c8e commit 1c4bf04

2 files changed

Lines changed: 40 additions & 7 deletions

File tree

ext/soap/php_http.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -956,14 +956,14 @@ int make_http_soap_request(zval *this_ptr,
956956
if (tmp != NULL) {
957957
tmp++;
958958
http_status = atoi(tmp);
959-
}
960-
tmp = strstr(tmp," ");
961-
if (tmp != NULL) {
962-
tmp++;
963-
if (http_msg) {
964-
efree(http_msg);
959+
tmp = strstr(tmp," ");
960+
if (tmp != NULL) {
961+
tmp++;
962+
if (http_msg) {
963+
efree(http_msg);
964+
}
965+
http_msg = estrdup(tmp);
965966
}
966-
http_msg = estrdup(tmp);
967967
}
968968
efree(http_version);
969969

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
SoapClient: malformed HTTP status line without status code must not crash
3+
--EXTENSIONS--
4+
soap
5+
--FILE--
6+
<?php
7+
$serverCode = <<<'CODE'
8+
$server = stream_socket_server("tcp://127.0.0.1:0", $errno, $errstr);
9+
phpt_notify_server_start($server);
10+
$conn = stream_socket_accept($server);
11+
while (($line = fgets($conn)) !== false) {
12+
if ($line === "\r\n" || $line === "\n") {
13+
break;
14+
}
15+
}
16+
fwrite($conn, "HTTP/1.1\r\nContent-Type: text/xml\r\nContent-Length: 0\r\n\r\n");
17+
fclose($conn);
18+
CODE;
19+
20+
$clientCode = <<<'CODE'
21+
$client = new SoapClient(null, [
22+
'location' => 'http://{{ ADDR }}',
23+
'uri' => 'http://testuri.org',
24+
'connection_timeout' => 3,
25+
]);
26+
var_dump($client->__doRequest('<x/>', 'http://{{ ADDR }}', 'T', 1));
27+
CODE;
28+
29+
include sprintf('%s/../../openssl/tests/ServerClientTestCase.inc', __DIR__);
30+
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
31+
?>
32+
--EXPECT--
33+
string(0) ""

0 commit comments

Comments
 (0)