Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 69328ba

Browse files
committed
Fix GH-18990, bug #81029, bug #47314: SOAP HTTP socket not closing on object destruction
Currently the resource is attached to the object and its refcount is increased. This means that the refcount to the resource is 2 instead of 1 as expected. A refcount of 2 is necessary in the current code because of how the error handling works: by using convert_to_null() the resource actually goes to rc_dtor_func(), dropping its refcount to 1. So on error the refcount is correct. To solve the issue, let `stream` conceptually be a borrow of the resource with refcount 1, and just use ZVAL_NULL() to prevent calling rc_dtor_func() on the resource. Closes GH-19001.
1 parent 09c223d commit 69328ba

File tree

3 files changed

+71
-12
lines changed

3 files changed

+71
-12
lines changed

‎NEWS‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ PHP NEWS
3232
. Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or
3333
pcntl_forkx() with zend-max-execution-timers). (Arnaud)
3434

35+
- SOAP:
36+
. Fixed bug GH-18990, bug #81029, bug #47314 (SOAP HTTP socket not closing
37+
on object destruction). (nielsdos)
38+
3539
- Standard:
3640
. Fix misleading errors in printf(). (nielsdos)
3741
. Fix RCN violations in array functions. (nielsdos)

‎ext/soap/php_http.c‎

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,9 @@ int make_http_soap_request(zval *this_ptr,
511511
zend_string_equals(orig->host, phpurl->host) &&
512512
orig->port == phpurl->port))) {
513513
} else {
514+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
514515
php_stream_close(stream);
515516
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
516-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
517517
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
518518
stream = NULL;
519519
use_proxy = 0;
@@ -522,9 +522,9 @@ int make_http_soap_request(zval *this_ptr,
522522

523523
/* Check if keep-alive connection is still opened */
524524
if (stream != NULL && php_stream_eof(stream)) {
525+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
525526
php_stream_close(stream);
526527
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
527-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
528528
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
529529
stream = NULL;
530530
use_proxy = 0;
@@ -533,9 +533,7 @@ int make_http_soap_request(zval *this_ptr,
533533
if (!stream) {
534534
stream = http_connect(this_ptr, phpurl, use_ssl, context, &use_proxy);
535535
if (stream) {
536-
php_stream_auto_cleanup(stream);
537-
ZVAL_RES(Z_CLIENT_HTTPSOCKET_P(this_ptr), stream->res);
538-
GC_ADDREF(stream->res);
536+
php_stream_to_zval(stream, Z_CLIENT_HTTPSOCKET_P(this_ptr));
539537
ZVAL_LONG(Z_CLIENT_USE_PROXY_P(this_ptr), use_proxy);
540538
} else {
541539
php_url_free(phpurl);
@@ -555,7 +553,6 @@ int make_http_soap_request(zval *this_ptr,
555553
zval *cookies, *login, *password;
556554
zend_resource *ret = zend_register_resource(phpurl, le_url);
557555
ZVAL_RES(Z_CLIENT_HTTPURL_P(this_ptr), ret);
558-
GC_ADDREF(ret);
559556

560557
if (context &&
561558
(tmp = php_stream_context_get_option(context, "http", "protocol_version")) != NULL &&
@@ -683,9 +680,9 @@ int make_http_soap_request(zval *this_ptr,
683680

684681
if (UNEXPECTED(php_random_bytes_throw(&nonce, sizeof(nonce)) != SUCCESS)) {
685682
ZEND_ASSERT(EG(exception));
683+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
686684
php_stream_close(stream);
687685
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
688-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
689686
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
690687
smart_str_free(&soap_headers_z);
691688
smart_str_free(&soap_headers);
@@ -901,9 +898,9 @@ int make_http_soap_request(zval *this_ptr,
901898
if (request != buf) {
902899
zend_string_release_ex(request, 0);
903900
}
901+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
904902
php_stream_close(stream);
905903
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
906-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
907904
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
908905
add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL);
909906
smart_str_free(&soap_headers_z);
@@ -919,8 +916,8 @@ int make_http_soap_request(zval *this_ptr,
919916
}
920917

921918
if (!return_value) {
919+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
922920
php_stream_close(stream);
923-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
924921
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
925922
smart_str_free(&soap_headers_z);
926923
efree(http_msg);
@@ -933,8 +930,8 @@ int make_http_soap_request(zval *this_ptr,
933930
if (request != buf) {
934931
zend_string_release_ex(request, 0);
935932
}
933+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
936934
php_stream_close(stream);
937-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
938935
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
939936
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
940937
smart_str_free(&soap_headers_z);
@@ -1102,9 +1099,9 @@ int make_http_soap_request(zval *this_ptr,
11021099
if (request != buf) {
11031100
zend_string_release_ex(request, 0);
11041101
}
1102+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
11051103
php_stream_close(stream);
11061104
zend_string_release_ex(http_headers, 0);
1107-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
11081105
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
11091106
add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL);
11101107
if (http_msg) {
@@ -1119,8 +1116,8 @@ int make_http_soap_request(zval *this_ptr,
11191116
}
11201117

11211118
if (http_close) {
1119+
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
11221120
php_stream_close(stream);
1123-
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
11241121
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
11251122
stream = NULL;
11261123
}

‎ext/soap/tests/bugs/gh18990.phpt‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
GH-18990 (SOAP HTTP socket not closing on object destruction)
3+
--INI--
4+
soap.wsdl_cache_enabled=0
5+
--EXTENSIONS--
6+
soap
7+
--SKIPIF--
8+
<?php
9+
require __DIR__.'/../../../standard/tests/http/server.inc';
10+
http_server_skipif();
11+
--FILE--
12+
<?php
13+
require __DIR__.'/../../../standard/tests/http/server.inc';
14+
15+
$wsdl = file_get_contents(__DIR__.'/../server030.wsdl');
16+
17+
$soap = <<<EOF
18+
<?xml version="1.0" encoding="UTF-8"?>
19+
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testuri.org" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getItemsResponse><getItemsReturn SOAP-ENC:arrayType="ns1:Item[10]" xsi:type="ns1:ItemArray"><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text0</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text1</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text2</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text3</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text4</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text5</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text6</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text7</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text8</text></item><item xsi:type="ns1:Item"><text xsi:type="xsd:string">text9</text></item></getItemsReturn></ns1:getItemsResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
20+
EOF;
21+
22+
$responses = [
23+
"data://text/plain,HTTP/1.1 200 OK\r\n".
24+
"Content-Type: text/xml;charset=utf-8\r\n".
25+
"Connection: Keep-Alive\r\n".
26+
"Content-Length: ".strlen($wsdl)."\r\n".
27+
"\r\n".
28+
$wsdl,
29+
30+
"data://text/plain,HTTP/1.1 200 OK\r\n".
31+
"Content-Type: text/xml;charset=utf-8\r\n".
32+
"Connection: Keep-Alive\r\n".
33+
"Content-Length: ".strlen($soap)."\r\n".
34+
"\r\n".
35+
$soap,
36+
];
37+
38+
['pid' => $pid, 'uri' => $uri] = http_server($responses);
39+
40+
$options = [
41+
'trace' => false,
42+
'location' => $uri,
43+
];
44+
45+
$cnt = count(get_resources());
46+
47+
$client = new SoapClient($uri, $options);
48+
49+
var_dump(count($client->getItems()));
50+
51+
http_server_kill($pid);
52+
53+
unset($client);
54+
var_dump(count(get_resources()) - $cnt);
55+
?>
56+
--EXPECT--
57+
int(10)
58+
int(0)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /