From fd0e7be55a77dd1d499c0b9df99d24e23e8c15e3 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 18 Jul 2017 02:50:40 -0700 Subject: [PATCH] Fix for memory leak in PILfont _font_text_asBytes, #2629 --- _imaging.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/_imaging.c b/_imaging.c index b7726a2cc..5e549a082 100644 --- a/_imaging.c +++ b/_imaging.c @@ -2198,26 +2198,45 @@ textwidth(ImagingFontObject* self, const unsigned char* text) } void _font_text_asBytes(PyObject* encoded_string, unsigned char** text){ + /* Allocates *text, returns a 'new reference'. Caller is required to free */ + PyObject* bytes = NULL; + ssize_t len = 0; + char *buffer; *text = NULL; if (PyUnicode_CheckExact(encoded_string)){ bytes = PyUnicode_AsLatin1String(encoded_string); + PyBytes_AsStringAndSize(bytes, &buffer, &len); } else if (PyBytes_Check(encoded_string)) { - bytes = encoded_string; + PyBytes_AsStringAndSize(encoded_string, &buffer, &len); } - if (bytes) { - *text = (unsigned char*)PyBytes_AsString(bytes); + + if (len) { + *text = calloc(len,1); + if (text) { + memcpy(*text, buffer, len); + } + if(bytes) { + Py_DECREF(bytes); + } return; } + #if PY_VERSION_HEX < 0x03000000 /* likely case here is py2.x with an ordinary string. but this isn't defined in Py3.x */ if (PyString_Check(encoded_string)) { - *text = (unsigned char *)PyString_AsString(encoded_string); + PyString_AsStringAndSize(encoded_string, &buffer, &len); + *text = calloc(len,1); + if (text) { + memcpy(*text, buffer, len); + } + return; } + #endif } @@ -2249,6 +2268,7 @@ _font_getmask(ImagingFontObject* self, PyObject* args) im = ImagingNew(self->bitmap->mode, textwidth(self, text), self->ysize); if (!im) { return NULL; + free(text); } b = 0; @@ -2273,9 +2293,11 @@ _font_getmask(ImagingFontObject* self, PyObject* args) x = x + glyph->dx; b = b + glyph->dy; } + free(text); return PyImagingNew(im); failed: + free(text); ImagingDelete(im); return NULL; } @@ -2285,6 +2307,7 @@ _font_getsize(ImagingFontObject* self, PyObject* args) { unsigned char* text; PyObject* encoded_string; + PyObject* val; if (!PyArg_ParseTuple(args, "O:getsize", &encoded_string)) return NULL; @@ -2294,7 +2317,9 @@ _font_getsize(ImagingFontObject* self, PyObject* args) return NULL; } - return Py_BuildValue("ii", textwidth(self, text), self->ysize); + val = Py_BuildValue("ii", textwidth(self, text), self->ysize); + free(text); + return val; } static struct PyMethodDef _font_methods[] = {