summaryrefslogtreecommitdiff
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
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.
-rw-r--r--NEWS1
-rw-r--r--ext/com_dotnet/com_persist.c11
-rw-r--r--ext/com_dotnet/tests/bug79332.phpt18
3 files changed, 20 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 49feabc5ef..3dd8545c44 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ PHP NEWS
. Fixed bug #79248 (Traversing empty VT_ARRAY throws com_exception). (cmb)
. Fixed bug #79299 (com_print_typeinfo prints duplicate variables). (Litiano
Moura)
+ . Fixed bug #79332 (php_istreams are never freed). (cmb)
- DOM:
. Fixed bug #77569: (Write Access Violation in DomImplementation). (Nikita,
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