From 7977b5fb82f77299c9ad129dede3216d237b4436 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 20 May 2020 02:58:42 -0400 Subject: [PATCH 1/3] Fix leak of input mesh during image resampling. Fixes #15474. --- src/_image_wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_image_wrapper.cpp b/src/_image_wrapper.cpp index a4c0e81db9ad..4c2eb0041400 100644 --- a/src/_image_wrapper.cpp +++ b/src/_image_wrapper.cpp @@ -85,7 +85,7 @@ _get_transform_mesh(PyObject *py_affine, npy_intp *dims) PyObject *output_mesh = PyObject_CallMethod( py_inverse, (char *)"transform", (char *)"O", - (char *)input_mesh.pyobj(), NULL); + (char *)input_mesh.pyobj_steal(), NULL); Py_DECREF(py_inverse); From ae0046890f81b2fc2ac8bf57e2d4f13b6247e3d5 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 20 May 2020 17:00:31 -0400 Subject: [PATCH 2/3] Fix leaking objects when saving PNG metadata. --- src/_png.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/_png.cpp b/src/_png.cpp index 0cc883df658e..1d0cfd41b1c2 100644 --- a/src/_png.cpp +++ b/src/_png.cpp @@ -139,11 +139,6 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds) numpy::array_view buffer; PyObject *filein; PyObject *metadata = NULL; - PyObject *meta_key, *meta_val; - png_text *text; - Py_ssize_t pos = 0; - int meta_pos = 0; - Py_ssize_t meta_size; double dpi = 0; int compression = 6; int filter = -1; @@ -274,8 +269,14 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds) PyErr_SetString(PyExc_TypeError, "metadata must be a dict or None"); goto exit; } - meta_size = PyDict_Size(metadata); - text = new png_text[meta_size]; + + Py_ssize_t meta_size = PyDict_Size(metadata); + png_text *text = new png_text[meta_size]; + PyObject *meta_key, *meta_val; + Py_ssize_t pos = 0; + int meta_pos = 0; + std::vector temp_strs; + temp_strs.reserve(meta_size); while (PyDict_Next(metadata, &pos, &meta_key, &meta_val)) { text[meta_pos].compression = PNG_TEXT_COMPRESSION_NONE; @@ -283,6 +284,7 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds) PyObject *temp_key = PyUnicode_AsEncodedString(meta_key, "latin_1", "strict"); if (temp_key != NULL) { text[meta_pos].key = PyBytes_AsString(temp_key); + temp_strs.push_back(temp_key); } } else if (PyBytes_Check(meta_key)) { text[meta_pos].key = PyBytes_AsString(meta_key); @@ -295,6 +297,7 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds) PyObject *temp_val = PyUnicode_AsEncodedString(meta_val, "latin_1", "strict"); if (temp_val != NULL) { text[meta_pos].text = PyBytes_AsString(temp_val); + temp_strs.push_back(temp_val); } } else if (PyBytes_Check(meta_val)) { text[meta_pos].text = PyBytes_AsString(meta_val); @@ -307,6 +310,10 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds) meta_pos++; } png_set_text(png_ptr, info_ptr, text, meta_size); + for (std::vector::iterator it = temp_strs.begin(); + it != temp_strs.end(); ++it) { + Py_DECREF(*it); + } delete[] text; } #endif From 8e13db1b904318e85bfab56eeec5213edf4f1745 Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 20 May 2020 17:01:23 -0400 Subject: [PATCH 3/3] Fix cleanup of PNG structures on error. If `info_ptr` isn't created, we should still destroy `png_ptr`. --- src/_png.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/_png.cpp b/src/_png.cpp index 1d0cfd41b1c2..b1bd5a3b8c64 100644 --- a/src/_png.cpp +++ b/src/_png.cpp @@ -346,8 +346,12 @@ static PyObject *Py_write_png(PyObject *self, PyObject *args, PyObject *kwds) png_write_end(png_ptr, info_ptr); exit: - if (png_ptr && info_ptr) { - png_destroy_write_struct(&png_ptr, &info_ptr); + if (png_ptr) { + if (info_ptr) { + png_destroy_write_struct(&png_ptr, &info_ptr); + } else { + png_destroy_write_struct(&png_ptr, NULL); + } } if (PyErr_Occurred()) { Py_XDECREF(buff.str);