mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
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.
This commit is contained in:
4
NEWS
4
NEWS
@@ -32,6 +32,10 @@ PHP NEWS
|
||||
. Fixed bug GH-18958 (Fatal error during shutdown after pcntl_rfork() or
|
||||
pcntl_forkx() with zend-max-execution-timers). (Arnaud)
|
||||
|
||||
- SOAP:
|
||||
. Fixed bug GH-18990, bug #81029, bug #47314 (SOAP HTTP socket not closing
|
||||
on object destruction). (nielsdos)
|
||||
|
||||
- Standard:
|
||||
. Fix misleading errors in printf(). (nielsdos)
|
||||
. Fix RCN violations in array functions. (nielsdos)
|
||||
|
||||
@@ -511,9 +511,9 @@ try_again:
|
||||
zend_string_equals(orig->host, phpurl->host) &&
|
||||
orig->port == phpurl->port))) {
|
||||
} else {
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
stream = NULL;
|
||||
use_proxy = 0;
|
||||
@@ -522,9 +522,9 @@ try_again:
|
||||
|
||||
/* Check if keep-alive connection is still opened */
|
||||
if (stream != NULL && php_stream_eof(stream)) {
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
stream = NULL;
|
||||
use_proxy = 0;
|
||||
@@ -533,9 +533,7 @@ try_again:
|
||||
if (!stream) {
|
||||
stream = http_connect(this_ptr, phpurl, use_ssl, context, &use_proxy);
|
||||
if (stream) {
|
||||
php_stream_auto_cleanup(stream);
|
||||
ZVAL_RES(Z_CLIENT_HTTPSOCKET_P(this_ptr), stream->res);
|
||||
GC_ADDREF(stream->res);
|
||||
php_stream_to_zval(stream, Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
ZVAL_LONG(Z_CLIENT_USE_PROXY_P(this_ptr), use_proxy);
|
||||
} else {
|
||||
php_url_free(phpurl);
|
||||
@@ -555,7 +553,6 @@ try_again:
|
||||
zval *cookies, *login, *password;
|
||||
zend_resource *ret = zend_register_resource(phpurl, le_url);
|
||||
ZVAL_RES(Z_CLIENT_HTTPURL_P(this_ptr), ret);
|
||||
GC_ADDREF(ret);
|
||||
|
||||
if (context &&
|
||||
(tmp = php_stream_context_get_option(context, "http", "protocol_version")) != NULL &&
|
||||
@@ -683,9 +680,9 @@ try_again:
|
||||
|
||||
if (UNEXPECTED(php_random_bytes_throw(&nonce, sizeof(nonce)) != SUCCESS)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
smart_str_free(&soap_headers_z);
|
||||
smart_str_free(&soap_headers);
|
||||
@@ -901,9 +898,9 @@ try_again:
|
||||
if (request != buf) {
|
||||
zend_string_release_ex(request, 0);
|
||||
}
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL);
|
||||
smart_str_free(&soap_headers_z);
|
||||
@@ -919,8 +916,8 @@ try_again:
|
||||
}
|
||||
|
||||
if (!return_value) {
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
smart_str_free(&soap_headers_z);
|
||||
efree(http_msg);
|
||||
@@ -933,8 +930,8 @@ try_again:
|
||||
if (request != buf) {
|
||||
zend_string_release_ex(request, 0);
|
||||
}
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
|
||||
smart_str_free(&soap_headers_z);
|
||||
@@ -1102,9 +1099,9 @@ try_again:
|
||||
if (request != buf) {
|
||||
zend_string_release_ex(request, 0);
|
||||
}
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
zend_string_release_ex(http_headers, 0);
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL);
|
||||
if (http_msg) {
|
||||
@@ -1119,8 +1116,8 @@ try_again:
|
||||
}
|
||||
|
||||
if (http_close) {
|
||||
ZVAL_NULL(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
php_stream_close(stream);
|
||||
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
|
||||
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
|
||||
stream = NULL;
|
||||
}
|
||||
|
||||
58
ext/soap/tests/bugs/gh18990.phpt
Normal file
58
ext/soap/tests/bugs/gh18990.phpt
Normal file
@@ -0,0 +1,58 @@
|
||||
--TEST--
|
||||
GH-18990 (SOAP HTTP socket not closing on object destruction)
|
||||
--INI--
|
||||
soap.wsdl_cache_enabled=0
|
||||
--EXTENSIONS--
|
||||
soap
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require __DIR__.'/../../../standard/tests/http/server.inc';
|
||||
http_server_skipif();
|
||||
--FILE--
|
||||
<?php
|
||||
require __DIR__.'/../../../standard/tests/http/server.inc';
|
||||
|
||||
$wsdl = file_get_contents(__DIR__.'/../server030.wsdl');
|
||||
|
||||
$soap = <<<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
EOF;
|
||||
|
||||
$responses = [
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n".
|
||||
"Content-Type: text/xml;charset=utf-8\r\n".
|
||||
"Connection: Keep-Alive\r\n".
|
||||
"Content-Length: ".strlen($wsdl)."\r\n".
|
||||
"\r\n".
|
||||
$wsdl,
|
||||
|
||||
"data://text/plain,HTTP/1.1 200 OK\r\n".
|
||||
"Content-Type: text/xml;charset=utf-8\r\n".
|
||||
"Connection: Keep-Alive\r\n".
|
||||
"Content-Length: ".strlen($soap)."\r\n".
|
||||
"\r\n".
|
||||
$soap,
|
||||
];
|
||||
|
||||
['pid' => $pid, 'uri' => $uri] = http_server($responses);
|
||||
|
||||
$options = [
|
||||
'trace' => false,
|
||||
'location' => $uri,
|
||||
];
|
||||
|
||||
$cnt = count(get_resources());
|
||||
|
||||
$client = new SoapClient($uri, $options);
|
||||
|
||||
var_dump(count($client->getItems()));
|
||||
|
||||
http_server_kill($pid);
|
||||
|
||||
unset($client);
|
||||
var_dump(count(get_resources()) - $cnt);
|
||||
?>
|
||||
--EXPECT--
|
||||
int(10)
|
||||
int(0)
|
||||
Reference in New Issue
Block a user