com php-src: Fixed bug #68887 (resources are not freed correctly): Zend/tests/bug68887.phpt ext/bz2/bz2.c ext/mysqlnd/mysqlnd_au th.c
ext/mysqlnd/mysqlnd_debug.c ext/sockets/sockets .c ext/spl/spl_directory.c ext/standard/file.c ex t/standard/filestat.c main/php_streams.h
main/streams /cast.c main/streams/streams.c
| From: | Dmitry Stogov | Date: | Wed, 08 Apr 2015 10:29:42 +0000 |
| Subject: | com php-src: Fixed bug #68887 (resources are not freed correctly): Zend/tests/bug68887.phpt ext/bz2/bz2.c ext/mysqlnd/mysqlnd_au th.c ext/mysqlnd/mysqlnd_debug.c ext/sockets/sockets .c ext/spl/spl_directory.c ext/standard/file.c ex t/standard/filestat.c main/php_streams.h main/streams /cast.c main/streams/streams.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-86124@lists.php.net to get a copy of this message | ||
Commit: 4d9a1883aa764e502990488d2e8b9c978be6fbd2
Author: Dmitry Stogov <dmitry@zend.com> Wed, 8 Apr 2015 13:29:42 +0300
Parents: fa795b05530c4ccd33ff63f23903bf4b458dc491
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=4d9a1883aa764e502990488d2e8b9c978be6fbd2
Log:
Fixed bug #68887 (resources are not freed correctly)
Bugs:
https://bugs.php.net/68887
Changed paths:
A Zend/tests/bug68887.phpt
M ext/bz2/bz2.c
M ext/mysqlnd/mysqlnd_auth.c
M ext/mysqlnd/mysqlnd_debug.c
M ext/sockets/sockets.c
M ext/spl/spl_directory.c
M ext/standard/file.c
M ext/standard/filestat.c
M main/php_streams.h
M main/streams/cast.c
M main/streams/streams.c
Diff:
diff --git a/Zend/tests/bug68887.phpt b/Zend/tests/bug68887.phpt
new file mode 100644
index 0000000..2c2a021
--- /dev/null
+++ b/Zend/tests/bug68887.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Bug #68887 (resources are not freed correctly)
+--FILE--
+<?php
+fclose(fopen("php://temp","w+"));
+$count = count(get_resources());
+fclose(fopen("php://temp","w+"));
+var_dump(count(get_resources()) == $count);
+fclose(fopen("php://temp","w+"));
+var_dump(count(get_resources()) == $count);
+?>
+--EXPECT--
+bool(true)
+bool(true)
diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c
index 921fc99..d4175c7 100644
--- a/ext/bz2/bz2.c
+++ b/ext/bz2/bz2.c
@@ -226,6 +226,9 @@ PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz,
self = emalloc(sizeof(*self));
self->stream = innerstream;
+ if (innerstream) {
+ GC_REFCOUNT(innerstream->res)++;
+ }
self->bz_file = bz;
return php_stream_alloc_rel(&php_stream_bz2io_ops, self, 0, mode);
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index e9eb773..2ecdd95 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -555,7 +555,7 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn,
DBG_INF_FMT("Public key:%*.s", key_str->len, key_str->val);
zend_string_release(key_str);
}
- php_stream_free(stream, PHP_STREAM_FREE_CLOSE);
+ php_stream_close(stream);
}
}
DBG_RETURN(ret);
diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c
index 812963a..790ac00 100644
--- a/ext/mysqlnd/mysqlnd_debug.c
+++ b/ext/mysqlnd/mysqlnd_debug.c
@@ -460,7 +460,7 @@ MYSQLND_METHOD(mysqlnd_debug, close)(MYSQLND_DEBUG * self)
}
#endif
- php_stream_free(self->stream, PHP_STREAM_FREE_CLOSE);
+ php_stream_close(self->stream);
self->stream = NULL;
}
/* no DBG_RETURN please */
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 45f7c25..19e1c76 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -1079,7 +1079,8 @@ PHP_FUNCTION(socket_close)
if (stream != NULL) {
/* close & destroy stream, incl. removing it from the rsrc list;
* resource stored in php_sock->zstream will become invalid */
- php_stream_free(stream, PHP_STREAM_FREE_CLOSE |
+ php_stream_free(stream,
+ PHP_STREAM_FREE_KEEP_RSRC | PHP_STREAM_FREE_CLOSE |
(stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0));
}
}
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 3e250b1..12c50c0 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -108,9 +108,9 @@ static void spl_filesystem_object_free_storage(zend_object *object) /* {{{ */
}
*/
if (!intern->u.file.stream->is_persistent) {
- php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE);
+ php_stream_close(intern->u.file.stream);
} else {
- php_stream_free(intern->u.file.stream, PHP_STREAM_FREE_CLOSE_PERSISTENT);
+ php_stream_pclose(intern->u.file.stream);
}
if (intern->u.file.open_mode) {
efree(intern->u.file.open_mode);
diff --git a/ext/standard/file.c b/ext/standard/file.c
index f31407b..fa9e752 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -900,11 +900,9 @@ PHPAPI PHP_FUNCTION(fclose)
RETURN_FALSE;
}
- if (!stream->is_persistent) {
- php_stream_close(stream);
- } else {
- php_stream_pclose(stream);
- }
+ php_stream_free(stream,
+ PHP_STREAM_FREE_KEEP_RSRC |
+ (stream->is_persistent ? PHP_STREAM_FREE_CLOSE_PERSISTENT : PHP_STREAM_FREE_CLOSE));
RETURN_TRUE;
}
diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c
index 54bc581..ffcba35 100644
--- a/ext/standard/filestat.c
+++ b/ext/standard/filestat.c
@@ -765,7 +765,7 @@ PHP_FUNCTION(touch)
}
stream = php_stream_open_wrapper_ex(filename, "c", REPORT_ERRORS, NULL, NULL);
if(stream != NULL) {
- php_stream_pclose(stream);
+ php_stream_close(stream);
RETURN_TRUE;
} else {
RETURN_FALSE;
diff --git a/main/php_streams.h b/main/php_streams.h
index 4f3d860..0ee3ff5 100644
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -284,6 +284,7 @@ PHPAPI int php_stream_from_persistent_id(const char *persistent_id, php_stream *
#define PHP_STREAM_FREE_RSRC_DTOR 8 /* called from the resource list dtor */
#define PHP_STREAM_FREE_PERSISTENT 16 /* manually freeing a persistent connection */
#define PHP_STREAM_FREE_IGNORE_ENCLOSING 32 /* don't close the enclosing stream instead */
+#define PHP_STREAM_FREE_KEEP_RSRC 64 /* keep associated zend_resource */
#define PHP_STREAM_FREE_CLOSE (PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_RELEASE_STREAM)
#define PHP_STREAM_FREE_CLOSE_CASTED (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PRESERVE_HANDLE)
#define PHP_STREAM_FREE_CLOSE_PERSISTENT (PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_PERSISTENT)
diff --git a/main/streams/cast.c b/main/streams/cast.c
index bc9cc80..23c59c7 100644
--- a/main/streams/cast.c
+++ b/main/streams/cast.c
@@ -86,7 +86,7 @@ static int stream_cookie_closer(void *cookie)
/* prevent recursion */
stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE;
- return php_stream_close(stream);
+ return php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_KEEP_RSRC);
}
#elif defined(HAVE_FOPENCOOKIE)
static ssize_t stream_cookie_reader(void *cookie, char *buffer, size_t size)
@@ -128,7 +128,7 @@ static int stream_cookie_closer(void *cookie)
/* prevent recursion */
stream->fclose_stdiocast = PHP_STREAM_FCLOSE_NONE;
- return php_stream_close(stream);
+ return php_stream_free(stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_KEEP_RSRC);
}
#endif /* elif defined(HAVE_FOPENCOOKIE) */
diff --git a/main/streams/streams.c b/main/streams/streams.c
index 886fc1d..2358cc9 100644
--- a/main/streams/streams.c
+++ b/main/streams/streams.c
@@ -439,15 +439,10 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d
release_cast=%d remov
/* If not called from the resource dtor, remove the stream from the resource list. */
if ((close_options & PHP_STREAM_FREE_RSRC_DTOR) == 0 && stream->res) {
- /* zend_list_delete actually only decreases the refcount; if we're
- * releasing the stream, we want to actually delete the resource from
- * the resource list, otherwise the resource will point to invalid memory.
- * In any case, let's always completely delete it from the resource list,
- * not only when PHP_STREAM_FREE_RELEASE_STREAM is set */
-//??? while (zend_list_delete(stream->res) == SUCCESS) {}
-//??? stream->res->gc.refcount = 0;
+ /* Close resource, but keep it in resource list */
zend_list_close(stream->res);
- if (!stream->__exposed) {
+ if ((close_options & PHP_STREAM_FREE_KEEP_RSRC) == 0) {
+ /* Completely delete zend_resource, if not referenced */
zend_list_delete(stream->res);
stream->res = NULL;
}