Commit d28bb624 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #24097: Fixed crash in object.__reduce__() if slot name is freed inside

__getattr__.  Original patch by Antoine Pitrou.
parent 33e7ea5a
...@@ -4988,6 +4988,23 @@ class PicklingTests(unittest.TestCase): ...@@ -4988,6 +4988,23 @@ class PicklingTests(unittest.TestCase):
objcopy2 = deepcopy(objcopy) objcopy2 = deepcopy(objcopy)
self._assert_is_copy(obj, objcopy2) self._assert_is_copy(obj, objcopy2)
def test_issue24097(self):
# Slot name is freed inside __getattr__ and is later used.
class S(str): # Not interned
pass
class A:
__slotnames__ = [S('spam')]
def __getattr__(self, attr):
if attr == 'spam':
A.__slotnames__[:] = [S('spam')]
return 42
else:
raise AttributeError
import copyreg
expected = (copyreg.__newobj__, (A,), (None, {'spam': 42}), None, None)
self.assertEqual(A().__reduce__(2), expected) # Shouldn't crash
class SharedKeyTests(unittest.TestCase): class SharedKeyTests(unittest.TestCase):
......
...@@ -10,6 +10,9 @@ Release date: tba ...@@ -10,6 +10,9 @@ Release date: tba
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #24097: Fixed crash in object.__reduce__() if slot name is freed inside
__getattr__.
- Issue #24731: Fixed crash on converting objects with special methods - Issue #24731: Fixed crash on converting objects with special methods
__bytes__, __trunc__, and __float__ returning instances of subclasses of __bytes__, __trunc__, and __float__ returning instances of subclasses of
bytes, int, and float to subclasses of bytes, int, and float correspondingly. bytes, int, and float to subclasses of bytes, int, and float correspondingly.
......
...@@ -3768,8 +3768,10 @@ _PyObject_GetState(PyObject *obj) ...@@ -3768,8 +3768,10 @@ _PyObject_GetState(PyObject *obj)
PyObject *name, *value; PyObject *name, *value;
name = PyList_GET_ITEM(slotnames, i); name = PyList_GET_ITEM(slotnames, i);
Py_INCREF(name);
value = PyObject_GetAttr(obj, name); value = PyObject_GetAttr(obj, name);
if (value == NULL) { if (value == NULL) {
Py_DECREF(name);
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
goto error; goto error;
} }
...@@ -3778,6 +3780,7 @@ _PyObject_GetState(PyObject *obj) ...@@ -3778,6 +3780,7 @@ _PyObject_GetState(PyObject *obj)
} }
else { else {
int err = PyDict_SetItem(slots, name, value); int err = PyDict_SetItem(slots, name, value);
Py_DECREF(name);
Py_DECREF(value); Py_DECREF(value);
if (err) { if (err) {
goto error; goto error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment