diff options
author | Amaury Forgeot d'Arc <amauryfa@gmail.com> | 2008-09-05 20:48:47 (GMT) |
---|---|---|
committer | Amaury Forgeot d'Arc <amauryfa@gmail.com> | 2008-09-05 20:48:47 (GMT) |
commit | f04811140339507ff461d5a79be4d088f4f06169 (patch) | |
tree | 657a6d3b3878b33146080b34dbd4b6c482e74a20 | |
parent | f9b99a0baa8eea460eaa8b7852f58b4cbb571fa5 (diff) | |
download | cpython-f04811140339507ff461d5a79be4d088f4f06169.zip cpython-f04811140339507ff461d5a79be4d088f4f06169.tar.gz cpython-f04811140339507ff461d5a79be4d088f4f06169.tar.bz2 |
#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.
-rw-r--r-- | Misc/NEWS | 7 | ||||
-rw-r--r-- | Objects/unicodeobject.c | 32 |
2 files changed, 24 insertions, 15 deletions
@@ -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 847b61d..66f617e 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; } |