]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords are not...
authorMichael Seifert <michaelseifert04@yahoo.de>
Wed, 15 Mar 2017 07:42:30 +0000 (08:42 +0100)
committerSerhiy Storchaka <storchaka@gmail.com>
Wed, 15 Mar 2017 07:42:30 +0000 (09:42 +0200)
Lib/test/test_functools.py
Misc/ACKS
Misc/NEWS
Modules/_functoolsmodule.c

index a82ca7ab88c38fea4a475897ce87c2a8d3fb9005..04ffab9a82dfc2c92f799f6bd0554d1f2d43e5aa 100644 (file)
@@ -387,6 +387,32 @@ class TestPartialC(TestPartial, unittest.TestCase):
         self.assertRaises(TypeError, f.__setstate__, BadSequence())
 
 
+    def test_manually_adding_non_string_keyword(self):
+        p = self.partial(capture)
+        # Adding a non-string/unicode keyword to partial kwargs
+        p.keywords[1234] = 'value'
+        r = repr(p)
+        self.assertIn('1234', r)
+        self.assertIn("'value'", r)
+        with self.assertRaises(TypeError):
+            p()
+
+    def test_keystr_replaces_value(self):
+        p = self.partial(capture)
+
+        class MutatesYourDict(object):
+            def __str__(self):
+                p.keywords[self] = ['sth2']
+                return 'astr'
+
+        # Raplacing the value during key formatting should keep the original
+        # value alive (at least long enough).
+        p.keywords[MutatesYourDict()] = ['sth']
+        r = repr(p)
+        self.assertIn('astr', r)
+        self.assertIn("['sth']", r)
+
+
 class TestPartialPy(TestPartial, unittest.TestCase):
     partial = staticmethod(py_functools.partial)
 
index d33ee913f49c416e68598b1680de1df56f3d938c..8a952a45f5dcd41e7bf4090efca05056738a0fcc 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1348,6 +1348,7 @@ Federico Schwindt
 Barry Scott
 Steven Scott
 Nick Seidenman
+Michael Seifert
 Žiga Seilnacht
 Yury Selivanov
 Fred Sells
index f12b5e665512ff436874601fb0527fc3c68fa29d..40d87e291d0f6e491c162634b0254f2e0645dbcc 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -43,6 +43,9 @@ Extension Modules
 Library
 -------
 
+- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
+  are not strings.  Patch by Michael Seifert.
+
 - bpo-29742: get_extra_info() raises exception if get called on closed ssl transport.
   Patch by Nikolay Kim.
 
index 0471d665e65a58e5f1ea7adf1eea404796fdce67..985bcb6985e835c64a1f2e0319663a6a21a8935b 100644 (file)
@@ -234,8 +234,11 @@ partial_repr(partialobject *pto)
     /* Pack keyword arguments */
     assert (PyDict_Check(pto->kw));
     for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
-        Py_SETREF(arglist, PyUnicode_FromFormat("%U, %U=%R", arglist,
+        /* Prevent key.__str__ from deleting the value. */
+        Py_INCREF(value);
+        Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
                                                 key, value));
+        Py_DECREF(value);
         if (arglist == NULL)
             goto done;
     }