summaryrefslogtreecommitdiff
path: root/ext/com_dotnet
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-03-02 10:45:37 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-03-02 10:45:37 +0100
commit2adf1c4d23467424012db1971d0a0a678d10d782 (patch)
treea222bfb3f5bc98f959dadaf6ac0acf3c09d95bea /ext/com_dotnet
parent6c48da9a50a68cbb27873ead6bf936494c006236 (diff)
downloadphp-git-2adf1c4d23467424012db1971d0a0a678d10d782.tar.gz
Fix #79332: php_istreams are never freed
Releasing the `com_dotnet_istream_wrapper` in `istream_destructor()` is pointless, since `istream_destructor()` is only called when the resource is going to be released. This recursion is not a real issue, though, since the resource is never exposed to userland, and has at most refcount 1, so due to well defined unsigned integer underflow, it never is released twice. However, returning early in this case causes a memory leak which needs to be fixed.
Diffstat (limited to 'ext/com_dotnet')
-rw-r--r--ext/com_dotnet/com_persist.c11
-rw-r--r--ext/com_dotnet/tests/bug79332.phpt18
2 files changed, 19 insertions, 10 deletions
diff --git a/ext/com_dotnet/com_persist.c b/ext/com_dotnet/com_persist.c
index 0fee0efd43..743a441f70 100644
--- a/ext/com_dotnet/com_persist.c
+++ b/ext/com_dotnet/com_persist.c
@@ -248,13 +248,6 @@ static struct IStreamVtbl php_istream_vtbl = {
static void istream_destructor(php_istream *stm)
{
- if (stm->res) {
- zend_resource *res = stm->res;
- stm->res = NULL;
- zend_list_delete(res);
- return;
- }
-
if (stm->refcount > 0) {
CoDisconnectObject((IUnknown*)stm, 0);
}
@@ -268,7 +261,6 @@ static void istream_destructor(php_istream *stm)
PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream)
{
php_istream *stm = (php_istream*)CoTaskMemAlloc(sizeof(*stm));
- zval *tmp;
if (stm == NULL)
return NULL;
@@ -280,8 +272,7 @@ PHP_COM_DOTNET_API IStream *php_com_wrapper_export_stream(php_stream *stream)
stm->stream = stream;
GC_ADDREF(stream->res);
- tmp = zend_list_insert(stm, le_istream);
- stm->res = Z_RES_P(tmp);
+ stm->res = zend_register_resource(stm, le_istream);
return (IStream*)stm;
}
diff --git a/ext/com_dotnet/tests/bug79332.phpt b/ext/com_dotnet/tests/bug79332.phpt
new file mode 100644
index 0000000000..45856b5488
--- /dev/null
+++ b/ext/com_dotnet/tests/bug79332.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #79332 (php_istreams are never freed)
+--SKIPIF--
+<?php
+if (!extension_loaded('com_dotnet')) die('com_dotnet extension not available');
+?>
+--FILE--
+<?php
+$ph = new COMPersistHelper(null);
+try {
+ $ph->LoadFromStream(fopen(__FILE__, 'r'));
+} catch (com_exception $ex) {
+ // use hard-coded message to avoid localization issues
+ echo "A com_exception has been thrown\n";
+}
+?>
+--EXPECT--
+A com_exception has been thrown