mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
gh-93627: Align Python implementation of pickle with C implementation of pickle (GH-103035)
If a method like __reduce_ex_ or __reduce__ is set to None, a TypeError is raised.
This commit is contained in:
parent
92578919a6
commit
85a5d3dbe1
3 changed files with 72 additions and 10 deletions
|
@ -2408,6 +2408,22 @@ class AbstractPickleTests:
|
|||
y = self.loads(s)
|
||||
self.assertEqual(y._reduce_called, 1)
|
||||
|
||||
def test_reduce_ex_None(self):
|
||||
c = REX_None()
|
||||
with self.assertRaises(TypeError):
|
||||
self.dumps(c)
|
||||
|
||||
def test_reduce_None(self):
|
||||
c = R_None()
|
||||
with self.assertRaises(TypeError):
|
||||
self.dumps(c)
|
||||
|
||||
def test_pickle_setstate_None(self):
|
||||
c = C_None_setstate()
|
||||
p = self.dumps(c)
|
||||
with self.assertRaises(TypeError):
|
||||
self.loads(p)
|
||||
|
||||
@no_tracing
|
||||
def test_bad_getattr(self):
|
||||
# Issue #3514: crash when there is an infinite loop in __getattr__
|
||||
|
@ -3349,6 +3365,21 @@ class REX_state(object):
|
|||
def __reduce__(self):
|
||||
return type(self), (), self.state
|
||||
|
||||
class REX_None:
|
||||
""" Setting __reduce_ex__ to None should fail """
|
||||
__reduce_ex__ = None
|
||||
|
||||
class R_None:
|
||||
""" Setting __reduce__ to None should fail """
|
||||
__reduce__ = None
|
||||
|
||||
class C_None_setstate:
|
||||
""" Setting __setstate__ to None should fail """
|
||||
def __getstate__(self):
|
||||
return 1
|
||||
|
||||
__setstate__ = None
|
||||
|
||||
|
||||
# Test classes for newobj
|
||||
|
||||
|
@ -3752,6 +3783,25 @@ class AbstractPicklerUnpicklerObjectTests:
|
|||
unpickler = self.unpickler_class(f)
|
||||
self.assertEqual(unpickler.load(), data)
|
||||
|
||||
def test_pickle_invalid_reducer_override(self):
|
||||
# gh-103035
|
||||
obj = object()
|
||||
|
||||
f = io.BytesIO()
|
||||
class MyPickler(self.pickler_class):
|
||||
pass
|
||||
pickler = MyPickler(f)
|
||||
pickler.dump(obj)
|
||||
|
||||
pickler.clear_memo()
|
||||
pickler.reducer_override = None
|
||||
with self.assertRaises(TypeError):
|
||||
pickler.dump(obj)
|
||||
|
||||
pickler.clear_memo()
|
||||
pickler.reducer_override = 10
|
||||
with self.assertRaises(TypeError):
|
||||
pickler.dump(obj)
|
||||
|
||||
# Tests for dispatch_table attribute
|
||||
|
||||
|
@ -3914,6 +3964,15 @@ class AbstractDispatchTableTests:
|
|||
|
||||
self._test_dispatch_table(dumps, dt)
|
||||
|
||||
def test_dispatch_table_None_item(self):
|
||||
# gh-93627
|
||||
obj = object()
|
||||
f = io.BytesIO()
|
||||
pickler = self.pickler_class(f)
|
||||
pickler.dispatch_table = {type(obj): None}
|
||||
with self.assertRaises(TypeError):
|
||||
pickler.dump(obj)
|
||||
|
||||
def _test_dispatch_table(self, dumps, dispatch_table):
|
||||
def custom_load_dump(obj):
|
||||
return pickle.loads(dumps(obj, 0))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue