- Fixed bug #61371 (resource leak). This bug had two parts, a long standing leak

already fixed in trunk/5.3 and now merged onto 5.4 and a leak introduced in
  fixing bug #61115. This better fix for #61115 fixes the leak (the inhibition
  for deleting the context was too broad) and so prevents segfaults in new
  circumstances (where the inhibition was not broad enough).
This commit is contained in:
Gustavo André dos Santos Lopes 2012-03-17 19:37:30 +00:00
parent 9bfe8010a0
commit d974e44248
6 changed files with 84 additions and 7 deletions

View File

@ -106,10 +106,6 @@ PHP_FUNCTION(stream_socket_client)
context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
if (context) {
zend_list_addref(context->rsrc_id);
}
if (flags & PHP_STREAM_CLIENT_PERSISTENT) {
spprintf(&hashkey, 0, "stream_socket_client__%s", host);
}

View File

@ -0,0 +1,11 @@
--TEST--
Bug #61115: Stream related segfault on fatal error in php_stream_context_del_link - variation 1
--FILE--
<?php
$fileResourceTemp = fopen('php://temp', 'wr');
stream_context_get_options($fileResourceTemp);
ftruncate($fileResourceTemp, PHP_INT_MAX);
?>
--EXPECTF--
Fatal error: Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes) in %s on line %d

View File

@ -0,0 +1,10 @@
--TEST--
Bug #61115: Stream related segfault on fatal error in php_stream_context_del_link - variation 2
--FILE--
<?php
stream_socket_client('abc', $var, $var, 0, STREAM_CLIENT_PERSISTENT);
?>
==DONE==
--EXPECT--
==DONE==

View File

@ -0,0 +1,13 @@
--TEST--
Bug #61115: Stream related segfault on fatal error in php_stream_context_del_link.
--FILE--
<?php
$arrayLarge = array_fill(0, 113663, '*');
$resourceFileTemp = fopen('php://temp', 'r+');
stream_context_set_params($resourceFileTemp, array());
preg_replace('', function() {}, $resourceFileTemp);
?>
--EXPECTF--
Catchable fatal error: Object of class Closure could not be converted to string in %s on line %d

View File

@ -0,0 +1,40 @@
--TEST--
Bug #61371: stream_context_create() causes memory leaks on use streams_socket_create
--FILE--
<?php
function test($doFclose) {
$previous = null;
$current = null;
for($test=1;$test<=3;$test++) {
$current = memory_get_usage(true);
if (!is_null($previous)) {
var_dump($previous == $current);
}
$previous = $current;
echo 'memory: '.round($current / 1024, 0)."kb\n";
for($i=0;$i<=100;$i++) {
$context = stream_context_create(array());
$stream = stream_socket_client('udp://0.0.0.0:80', $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
if ($doFclose) fclose($stream);
unset($context);
unset($stream);
unset($errno);
unset($errstr);
}
}
}
test(true);
test(false);
?>
--EXPECTF--
memory: %dkb
bool(true)
memory: %dkb
bool(true)
memory: %dkb
memory: %dkb
bool(true)
memory: %dkb
bool(true)
memory: %dkb

View File

@ -385,7 +385,14 @@ PHPAPI int _php_stream_free(php_stream *stream, int close_options TSRMLS_DC) /*
int ret = 1;
int preserve_handle = close_options & PHP_STREAM_FREE_PRESERVE_HANDLE ? 1 : 0;
int release_cast = 1;
php_stream_context *context = stream->context;
php_stream_context *context = NULL;
/* on an resource list destruction, the context, another resource, may have
* already been freed (if it was created after the stream resource), so
* don't reference it */
if (EG(active)) {
context = stream->context;
}
if (stream->flags & PHP_STREAM_FLAG_NO_CLOSE) {
preserve_handle = 1;
@ -464,8 +471,8 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
}
/* Remove stream from any context link list */
if (stream->context && stream->context->links) {
php_stream_context_del_link(stream->context, stream);
if (context && context->links) {
php_stream_context_del_link(context, stream);
}
if (close_options & PHP_STREAM_FREE_CALL_DTOR) {