From ef5f0ac984f233c3ae10da00d97a7e50d5b05514 Mon Sep 17 00:00:00 2001 From: Ryan May Date: Fri, 11 Jul 2014 01:41:16 -0500 Subject: [PATCH] Fix memory leak in tostring_rgba_minimize(). (#3197) The APIs being used in PyCXX (and Python C-API) were not actually taking ownership. Instead, make Python allocate memory. --- src/_backend_agg.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/_backend_agg.cpp b/src/_backend_agg.cpp index 8d1483188d51..c35a9da93cbb 100644 --- a/src/_backend_agg.cpp +++ b/src/_backend_agg.cpp @@ -2401,13 +2401,24 @@ RendererAgg::tostring_rgba_minimized(const Py::Tuple& args) newheight = ymax - ymin; int newsize = newwidth * newheight * 4; - unsigned char* buf = new unsigned char[newsize]; - if (buf == NULL) + // NULL pointer causes Python to allocate uninitialized memory. + // We then grab Python's pointer to uninitialized memory using + // the _AsString() API. + unsigned int* dst; + + #if PY3K + data = Py::Bytes(static_cast(NULL), (int) newsize); + dst = reinterpret_cast(PyBytes_AsString(data.ptr())); + #else + data = Py::String(static_cast(NULL), (int) newsize); + dst = reinterpret_cast(PyString_AsString(data.ptr())); + #endif + + if (dst == NULL) { throw Py::MemoryError("RendererAgg::tostring_minimized could not allocate memory"); } - unsigned int* dst = (unsigned int*)buf; unsigned int* src = (unsigned int*)pixBuffer; for (int y = ymin; y < ymax; ++y) { @@ -2416,13 +2427,6 @@ RendererAgg::tostring_rgba_minimized(const Py::Tuple& args) *dst = src[y * width + x]; } } - - // The Py::String will take over the buffer - #if PY3K - data = Py::Bytes((const char *)buf, (int) newsize); - #else - data = Py::String((const char *)buf, (int) newsize); - #endif } Py::Tuple bounds(4);