Skip to content

Commit 6c3d527

Browse files
MSeifert04serhiy-storchaka
authored andcommitted
bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords are not strings (#649)
1 parent 024b4fd commit 6c3d527

File tree

4 files changed

+34
-1
lines changed

4 files changed

+34
-1
lines changed

Lib/test/test_functools.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,32 @@ def test_attributes_unwritable(self):
403403
else:
404404
self.fail('partial object allowed __dict__ to be deleted')
405405

406+
def test_manually_adding_non_string_keyword(self):
407+
p = self.partial(capture)
408+
# Adding a non-string/unicode keyword to partial kwargs
409+
p.keywords[1234] = 'value'
410+
r = repr(p)
411+
self.assertIn('1234', r)
412+
self.assertIn("'value'", r)
413+
with self.assertRaises(TypeError):
414+
p()
415+
416+
def test_keystr_replaces_value(self):
417+
p = self.partial(capture)
418+
419+
class MutatesYourDict(object):
420+
def __str__(self):
421+
p.keywords[self] = ['sth2']
422+
return 'astr'
423+
424+
# Raplacing the value during key formatting should keep the original
425+
# value alive (at least long enough).
426+
p.keywords[MutatesYourDict()] = ['sth']
427+
r = repr(p)
428+
self.assertIn('astr', r)
429+
self.assertIn("['sth']", r)
430+
431+
406432
class TestPartialPy(TestPartial, unittest.TestCase):
407433
partial = py_functools.partial
408434

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,7 @@ Federico Schwindt
13741374
Barry Scott
13751375
Steven Scott
13761376
Nick Seidenman
1377+
Michael Seifert
13771378
Žiga Seilnacht
13781379
Yury Selivanov
13791380
Fred Sells

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ Extension Modules
281281
Library
282282
-------
283283

284+
- bpo-29800: Fix crashes in partial.__repr__ if the keys of partial.keywords
285+
are not strings. Patch by Michael Seifert.
286+
284287
- bpo-8256: Fixed possible failing or crashing input() if attributes "encoding"
285288
or "errors" of sys.stdin or sys.stdout are not set or are not strings.
286289

Modules/_functoolsmodule.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,11 @@ partial_repr(partialobject *pto)
297297
/* Pack keyword arguments */
298298
assert (PyDict_Check(pto->kw));
299299
for (i = 0; PyDict_Next(pto->kw, &i, &key, &value);) {
300-
Py_SETREF(arglist, PyUnicode_FromFormat("%U, %U=%R", arglist,
300+
/* Prevent key.__str__ from deleting the value. */
301+
Py_INCREF(value);
302+
Py_SETREF(arglist, PyUnicode_FromFormat("%U, %S=%R", arglist,
301303
key, value));
304+
Py_DECREF(value);
302305
if (arglist == NULL)
303306
goto done;
304307
}

0 commit comments

Comments
 (0)