]> granicus.if.org Git - python/commitdiff
#3660: Correct a reference leak in PyUnicode_AsEncodedString when
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Fri, 5 Sep 2008 20:48:47 +0000 (20:48 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Fri, 5 Sep 2008 20:48:47 +0000 (20:48 +0000)
the encoder does not return a bytes object.

Now test_unicode passes without leaking.

Reviewer: Antoine Pitrou.

Misc/NEWS
Objects/unicodeobject.c

index 1bb4f6f4f91a0b926ce2d13a3e89ad16f713ebfb..f388f11a81b316792edeba399bf5c482bec3b2f1 100644 (file)
--- 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().
 
index 847b61df918726077481989db5674ee98c3193fb..66f617e43a9018b2c5c1ca3caecb1665b2d3c3cf 100644 (file)
@@ -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;
 }