Skip to content

Commit 92e4e8b

Browse files
committed
Fix #49278: SoapClient::__getLastResponseHeaders returns NULL if wsdl operation !has output
Instead of early exiting, process the headers if tracing is enabled, and exit after that. Closes GH-12609.
1 parent ccdc21b commit 92e4e8b

File tree

4 files changed

+172
-50
lines changed

4 files changed

+172
-50
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ SOAP:
4646
. Add support for clark notation for namespaces in class map. (lxShaDoWxl)
4747
. Mitigate #51561 (SoapServer with a extented class and using sessions,
4848
lost the setPersistence()). (nielsdos)
49+
. Fixed bug #49278 (SoapClient::__getLastResponseHeaders returns NULL if
50+
wsdl operation !has output). (nielsdos)
4951

5052
Sockets:
5153
. Removed the deprecated inet_ntoa call support. (David Carlier)

ext/soap/php_http.c

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,8 @@ int make_http_soap_request(zval *this_ptr,
532532
}
533533
PG(allow_url_fopen) = old_allow_url_fopen;
534534

535+
bool client_trace = Z_TYPE_P(Z_CLIENT_TRACE_P(this_ptr)) == IS_TRUE;
536+
535537
if (stream) {
536538
zval *cookies, *login, *password;
537539
zend_resource *ret = zend_register_resource(phpurl, le_url);
@@ -863,7 +865,7 @@ int make_http_soap_request(zval *this_ptr,
863865

864866
smart_str_append_const(&soap_headers, "\r\n");
865867
smart_str_0(&soap_headers);
866-
if (Z_TYPE_P(Z_CLIENT_TRACE_P(this_ptr)) == IS_TRUE) {
868+
if (client_trace) {
867869
zval_ptr_dtor(Z_CLIENT_LAST_REQUEST_HEADERS_P(this_ptr));
868870
/* Need to copy the string here, as we continue appending to soap_headers below. */
869871
ZVAL_STRINGL(Z_CLIENT_LAST_REQUEST_HEADERS_P(this_ptr),
@@ -892,65 +894,78 @@ int make_http_soap_request(zval *this_ptr,
892894
return FALSE;
893895
}
894896

895-
if (!return_value) {
896-
php_stream_close(stream);
897-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
898-
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
899-
smart_str_free(&soap_headers_z);
900-
return TRUE;
901-
}
897+
http_headers = NULL;
898+
if (return_value || client_trace) {
899+
do {
900+
http_headers = get_http_headers(stream);
901+
if (!http_headers) {
902+
if (request != buf) {
903+
zend_string_release_ex(request, 0);
904+
}
905+
php_stream_close(stream);
906+
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
907+
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
908+
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
909+
smart_str_free(&soap_headers_z);
910+
return FALSE;
911+
}
902912

903-
do {
904-
http_headers = get_http_headers(stream);
905-
if (!http_headers) {
906-
if (request != buf) {
907-
zend_string_release_ex(request, 0);
913+
if (client_trace) {
914+
zval_ptr_dtor(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr));
915+
ZVAL_STR_COPY(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr), http_headers);
908916
}
909-
php_stream_close(stream);
910-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
911-
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
912-
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
913-
smart_str_free(&soap_headers_z);
914-
return FALSE;
915-
}
916917

917-
if (Z_TYPE_P(Z_CLIENT_TRACE_P(this_ptr)) == IS_TRUE) {
918-
zval_ptr_dtor(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr));
919-
ZVAL_STR_COPY(Z_CLIENT_LAST_RESPONSE_HEADERS_P(this_ptr), http_headers);
920-
}
918+
/* Check to see what HTTP status was sent */
919+
http_1_1 = 0;
920+
http_status = 0;
921+
http_version = get_http_header_value(ZSTR_VAL(http_headers), "HTTP/");
922+
if (http_version) {
923+
char *tmp;
921924

922-
/* Check to see what HTTP status was sent */
923-
http_1_1 = 0;
924-
http_status = 0;
925-
http_version = get_http_header_value(ZSTR_VAL(http_headers), "HTTP/");
926-
if (http_version) {
927-
char *tmp;
925+
if (!strncmp(http_version,"1.1", 3)) {
926+
http_1_1 = 1;
927+
}
928928

929-
if (!strncmp(http_version,"1.1", 3)) {
930-
http_1_1 = 1;
931-
}
929+
tmp = strstr(http_version," ");
930+
if (tmp != NULL) {
931+
tmp++;
932+
http_status = atoi(tmp);
933+
}
934+
tmp = strstr(tmp," ");
935+
if (tmp != NULL) {
936+
tmp++;
937+
if (http_msg) {
938+
efree(http_msg);
939+
}
940+
http_msg = estrdup(tmp);
941+
}
942+
efree(http_version);
932943

933-
tmp = strstr(http_version," ");
934-
if (tmp != NULL) {
935-
tmp++;
936-
http_status = atoi(tmp);
937-
}
938-
tmp = strstr(tmp," ");
939-
if (tmp != NULL) {
940-
tmp++;
941-
if (http_msg) {
942-
efree(http_msg);
944+
/* Try and get headers again */
945+
if (http_status == 100) {
946+
zend_string_release_ex(http_headers, 0);
943947
}
944-
http_msg = estrdup(tmp);
945948
}
946-
efree(http_version);
949+
} while (http_status == 100);
950+
}
947951

948-
/* Try and get headers again */
949-
if (http_status == 100) {
950-
zend_string_release_ex(http_headers, 0);
951-
}
952+
if (!return_value) {
953+
/* In this case, the headers were only fetched because client_trace was true. */
954+
if (request != buf) {
955+
zend_string_release_ex(request, 0);
956+
}
957+
php_stream_close(stream);
958+
if (http_headers) {
959+
zend_string_release_ex(http_headers, 0);
960+
}
961+
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
962+
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
963+
if (http_msg) {
964+
efree(http_msg);
952965
}
953-
} while (http_status == 100);
966+
smart_str_free(&soap_headers_z);
967+
return true;
968+
}
954969

955970
/* Grab and send back every cookie */
956971

ext/soap/tests/bugs/bug49278.phpt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
--TEST--
2+
Bug #49278 (SoapClient::__getLastResponseHeaders returns NULL if wsdl operation !has output)
3+
--EXTENSIONS--
4+
soap
5+
--INI--
6+
soap.wsdl_cache_enabled=0
7+
--SKIPIF--
8+
<?php
9+
if (!file_exists(__DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc")) {
10+
echo "skip sapi/cli/tests/php_cli_server.inc required but not found";
11+
}
12+
?>
13+
--FILE--
14+
<?php
15+
16+
include __DIR__ . "/../../../../sapi/cli/tests/php_cli_server.inc";
17+
18+
$args = ["-d", "extension_dir=" . ini_get("extension_dir"), "-d", "extension=" . (substr(PHP_OS, 0, 3) == "WIN" ? "php_" : "") . "soap." . PHP_SHLIB_SUFFIX];
19+
if (php_ini_loaded_file()) {
20+
// Necessary such that it works from a development directory in which case extension_dir might not be the real extension dir
21+
$args[] = "-c";
22+
$args[] = php_ini_loaded_file();
23+
}
24+
$code = '$server = new SoapServer("' . __DIR__ . '"/bug49278.wsdl", ["trace"=>1]);' .
25+
<<<'PHP'
26+
function Add() {}
27+
$server->addFunction('Add');
28+
$server->handle();
29+
PHP;
30+
31+
php_cli_server_start($code, null, $args);
32+
33+
$client = new SoapClient(__DIR__ . '/bug49278.wsdl', array('location' => "http://".PHP_CLI_SERVER_ADDRESS, 'trace' => 1));
34+
$client->Add();
35+
var_dump($client->__getLastResponse());
36+
var_dump($client->__getLastResponse());
37+
var_dump($client->__getLastRequestHeaders());
38+
var_dump($client->__getLastResponseHeaders());
39+
40+
?>
41+
--EXPECTF--
42+
string(0) ""
43+
string(0) ""
44+
string(177) "POST / HTTP/1.1
45+
Host: %s
46+
Connection: Keep-Alive
47+
User-Agent: PHP-SOAP/8.4.0-dev
48+
Content-Type: text/xml; charset=utf-8
49+
SOAPAction: "Add"
50+
Content-Length: %d
51+
52+
"
53+
string(165) "HTTP/1.1 200 OK
54+
Host: %s
55+
Date: %s
56+
Connection: close
57+
X-Powered-By: PHP/8.4.0-dev
58+
Content-type: text/html; charset=UTF-8
59+
"

ext/soap/tests/bugs/bug49278.wsdl

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" ?>
2+
<definitions
3+
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
4+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
7+
xmlns:si="http://soapinterop.org/xsd"
8+
xmlns:tns="http://linuxsrv.home/~dmitry/soap/test.wsdl"
9+
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
10+
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
11+
xmlns="http://schemas.xmlsoap.org/wsdl/"
12+
targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
13+
14+
<types>
15+
<xsd:schema targetNamespace="http://linuxsrv.home/~dmitry/soap/test.wsdl">
16+
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
17+
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
18+
</xsd:schema>
19+
</types>
20+
21+
<message name="AddRequest"/>
22+
<message name="AddResponse"/>
23+
24+
<portType name="TestServicePortType">
25+
<operation name="Add">
26+
<input message="tns:AddRequest" />
27+
</operation>
28+
</portType>
29+
30+
<binding name="TestServiceBinding" type="tns:TestServicePortType">
31+
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
32+
<operation name="Add">
33+
<soap:operation soapAction="Add" style="rpc" />
34+
<input>
35+
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
36+
</input>
37+
</operation>
38+
</binding>
39+
40+
<service name="TestService">
41+
<port name="TestServicePort" binding="tns:TestServiceBinding">
42+
<soap:address location="http://linuxsrv.home/~dmitry/soap/soap_server.php" />
43+
</port>
44+
</service>
45+
46+
</definitions>

0 commit comments

Comments
 (0)