From d974e4424837042e1ccaebe7be2b47e6006fc456 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Sat, 17 Mar 2012 19:37:30 +0000 Subject: [PATCH] - 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). --- ext/standard/streamsfuncs.c | 4 --- ext/standard/tests/streams/bug61115-1.phpt | 11 ++++++ ext/standard/tests/streams/bug61115-2.phpt | 10 ++++++ ext/standard/tests/streams/bug61115.phpt | 13 +++++++ ext/standard/tests/streams/bug61371.phpt | 40 ++++++++++++++++++++++ main/streams/streams.c | 13 +++++-- 6 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 ext/standard/tests/streams/bug61115-1.phpt create mode 100644 ext/standard/tests/streams/bug61115-2.phpt create mode 100644 ext/standard/tests/streams/bug61115.phpt create mode 100644 ext/standard/tests/streams/bug61371.phpt diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index c903c57594..86e0bc6e60 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -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); } diff --git a/ext/standard/tests/streams/bug61115-1.phpt b/ext/standard/tests/streams/bug61115-1.phpt new file mode 100644 index 0000000000..43c54b4974 --- /dev/null +++ b/ext/standard/tests/streams/bug61115-1.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #61115: Stream related segfault on fatal error in php_stream_context_del_link - variation 1 +--FILE-- + +--EXPECTF-- +Fatal error: Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes) in %s on line %d diff --git a/ext/standard/tests/streams/bug61115-2.phpt b/ext/standard/tests/streams/bug61115-2.phpt new file mode 100644 index 0000000000..260b8369df --- /dev/null +++ b/ext/standard/tests/streams/bug61115-2.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #61115: Stream related segfault on fatal error in php_stream_context_del_link - variation 2 +--FILE-- + +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/standard/tests/streams/bug61115.phpt b/ext/standard/tests/streams/bug61115.phpt new file mode 100644 index 0000000000..29dc7c1ccc --- /dev/null +++ b/ext/standard/tests/streams/bug61115.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #61115: Stream related segfault on fatal error in php_stream_context_del_link. +--FILE-- + +--EXPECTF-- +Catchable fatal error: Object of class Closure could not be converted to string in %s on line %d diff --git a/ext/standard/tests/streams/bug61371.phpt b/ext/standard/tests/streams/bug61371.phpt new file mode 100644 index 0000000000..7fbfa56ba2 --- /dev/null +++ b/ext/standard/tests/streams/bug61371.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #61371: stream_context_create() causes memory leaks on use streams_socket_create +--FILE-- + +--EXPECTF-- +memory: %dkb +bool(true) +memory: %dkb +bool(true) +memory: %dkb +memory: %dkb +bool(true) +memory: %dkb +bool(true) +memory: %dkb diff --git a/main/streams/streams.c b/main/streams/streams.c index 390db1d1ce..161430754e 100755 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -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) { -- 2.50.1