diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index c9ebdb8dc93..a622145a9da 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -868,6 +868,14 @@ class AbstractPickleTests(unittest.TestCase): y = self.loads(s) self.assertEqual(y._reduce_called, 1) + def test_bad_getattr(self): + x = BadGetattr() + for proto in 0, 1: + self.assertRaises(RuntimeError, self.dumps, x, proto) + # protocol 2 don't raise a RuntimeError. + d = self.dumps(x, 2) + self.assertRaises(RuntimeError, self.loads, d) + # Test classes for reduce_ex class REX_one(object): @@ -949,6 +957,10 @@ class SimpleNewObj(object): # raise an error, to make sure this isn't called raise TypeError("SimpleNewObj.__init__() didn't expect to get called") +class BadGetattr: + def __getattr__(self, key): + self.foo + class AbstractPickleModuleTests(unittest.TestCase): def test_dump_closed_file(self): diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 0f5b06bea8d..52fa15694cd 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -3834,8 +3834,11 @@ load_build(UnpicklerObject *self) inst = self->stack->data[self->stack->length - 1]; setstate = PyObject_GetAttrString(inst, "__setstate__"); - if (setstate == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); + if (setstate == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return -1; } else { PyObject *result;