Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1f9d907

Browse files
committed
Issue 3514: Fixed segfault dues to infinite loop in __getattr__.
1 parent e1e48ea commit 1f9d907

2 files changed

Lines changed: 17 additions & 2 deletions

File tree

Lib/test/pickletester.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,14 @@ def test_reduce_calls_base(self):
868868
y = self.loads(s)
869869
self.assertEqual(y._reduce_called, 1)
870870

871+
def test_bad_getattr(self):
872+
x = BadGetattr()
873+
for proto in 0, 1:
874+
self.assertRaises(RuntimeError, self.dumps, x, proto)
875+
# protocol 2 don't raise a RuntimeError.
876+
d = self.dumps(x, 2)
877+
self.assertRaises(RuntimeError, self.loads, d)
878+
871879
# Test classes for reduce_ex
872880

873881
class REX_one(object):
@@ -949,6 +957,10 @@ def __init__(self, a, b, c):
949957
# raise an error, to make sure this isn't called
950958
raise TypeError("SimpleNewObj.__init__() didn't expect to get called")
951959

960+
class BadGetattr:
961+
def __getattr__(self, key):
962+
self.foo
963+
952964
class AbstractPickleModuleTests(unittest.TestCase):
953965

954966
def test_dump_closed_file(self):

Modules/_pickle.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,8 +3834,11 @@ load_build(UnpicklerObject *self)
38343834
inst = self->stack->data[self->stack->length - 1];
38353835

38363836
setstate = PyObject_GetAttrString(inst, "__setstate__");
3837-
if (setstate == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
3838-
PyErr_Clear();
3837+
if (setstate == NULL) {
3838+
if (PyErr_ExceptionMatches(PyExc_AttributeError))
3839+
PyErr_Clear();
3840+
else
3841+
return -1;
38393842
}
38403843
else {
38413844
PyObject *result;

0 commit comments

Comments
 (0)