From f04811140339507ff461d5a79be4d088f4f06169 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 5 Sep 2008 20:48:47 +0000 Subject: [PATCH] #3660: Correct a reference leak in PyUnicode_AsEncodedString when the encoder does not return a bytes object. Now test_unicode passes without leaking. Reviewer: Antoine Pitrou. --- Misc/NEWS | 7 +++++-- Objects/unicodeobject.c | 32 +++++++++++++++++++------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS index 1bb4f6f4f9..f388f11a81 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,10 +12,13 @@ What's New in Python 3.0 release candidate 1 Core and Builtins ----------------- -- Issue 3774: Added a few more checks in PyTokenizer_FindEncoding to handle +- Issue #3660: Corrected a reference leak in str.encode() when the encoder + does not return a bytes object. + +- Issue #3774: Added a few more checks in PyTokenizer_FindEncoding to handle error conditions. -- Issue 3594: Fix Parser/tokenizer.c:fp_setreadl() to open the file being +- Issue #3594: Fix Parser/tokenizer.c:fp_setreadl() to open the file being tokenized by either a file path or file pointer for the benefit of PyTokenizer_FindEncoding(). diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 847b61df91..66f617e43a 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1328,7 +1328,7 @@ PyObject *PyUnicode_AsEncodedString(PyObject *unicode, if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); - goto onError; + return NULL; } if (encoding == NULL) @@ -1351,27 +1351,33 @@ PyObject *PyUnicode_AsEncodedString(PyObject *unicode, /* Encode via the codec registry */ v = PyCodec_Encode(unicode, encoding, errors); if (v == NULL) - goto onError; + return NULL; + + /* The normal path */ + if (PyBytes_Check(v)) + return v; + + /* If the codec returns a buffer, raise a warning and convert to bytes */ if (PyByteArray_Check(v)) { char msg[100]; + PyObject *b; PyOS_snprintf(msg, sizeof(msg), "encoder %s returned buffer instead of bytes", encoding); if (PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1) < 0) { - v = NULL; - goto onError; + Py_DECREF(v); + return NULL; } - v = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(v), Py_SIZE(v)); - } - else if (!PyBytes_Check(v)) { - PyErr_Format(PyExc_TypeError, - "encoder did not return a bytes object (type=%.400s)", - Py_TYPE(v)->tp_name); - v = NULL; + + b = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(v), Py_SIZE(v)); + Py_DECREF(v); + return b; } - return v; - onError: + PyErr_Format(PyExc_TypeError, + "encoder did not return a bytes object (type=%.400s)", + Py_TYPE(v)->tp_name); + Py_DECREF(v); return NULL; } -- 2.40.0