mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
gh-92930: _pickle.c: Acquire strong references before calling save() (GH-92931)
(cherry picked from commit 4c496f1f11
)
Co-authored-by: Dennis Sweeney <36520290+sweeneyde@users.noreply.github.com>
This commit is contained in:
parent
65e2a940fa
commit
1190b63721
3 changed files with 98 additions and 11 deletions
|
@ -3032,6 +3032,67 @@ class AbstractPickleTests:
|
|||
# 2-D, non-contiguous
|
||||
check_array(arr[::2])
|
||||
|
||||
def test_evil_class_mutating_dict(self):
|
||||
# https://github.com/python/cpython/issues/92930
|
||||
from random import getrandbits
|
||||
|
||||
global Bad
|
||||
class Bad:
|
||||
def __eq__(self, other):
|
||||
return ENABLED
|
||||
def __hash__(self):
|
||||
return 42
|
||||
def __reduce__(self):
|
||||
if getrandbits(6) == 0:
|
||||
collection.clear()
|
||||
return (Bad, ())
|
||||
|
||||
for proto in protocols:
|
||||
for _ in range(20):
|
||||
ENABLED = False
|
||||
collection = {Bad(): Bad() for _ in range(20)}
|
||||
for bad in collection:
|
||||
bad.bad = bad
|
||||
bad.collection = collection
|
||||
ENABLED = True
|
||||
try:
|
||||
data = self.dumps(collection, proto)
|
||||
self.loads(data)
|
||||
except RuntimeError as e:
|
||||
expected = "changed size during iteration"
|
||||
self.assertIn(expected, str(e))
|
||||
|
||||
def test_evil_pickler_mutating_collection(self):
|
||||
# https://github.com/python/cpython/issues/92930
|
||||
if not hasattr(self, "pickler"):
|
||||
raise self.skipTest(f"{type(self)} has no associated pickler type")
|
||||
|
||||
global Clearer
|
||||
class Clearer:
|
||||
pass
|
||||
|
||||
def check(collection):
|
||||
class EvilPickler(self.pickler):
|
||||
def persistent_id(self, obj):
|
||||
if isinstance(obj, Clearer):
|
||||
collection.clear()
|
||||
return None
|
||||
pickler = EvilPickler(io.BytesIO(), proto)
|
||||
try:
|
||||
pickler.dump(collection)
|
||||
except RuntimeError as e:
|
||||
expected = "changed size during iteration"
|
||||
self.assertIn(expected, str(e))
|
||||
|
||||
for proto in protocols:
|
||||
check([Clearer()])
|
||||
check([Clearer(), Clearer()])
|
||||
check({Clearer()})
|
||||
check({Clearer(), Clearer()})
|
||||
check({Clearer(): 1})
|
||||
check({Clearer(): 1, Clearer(): 2})
|
||||
check({1: Clearer(), 2: Clearer()})
|
||||
|
||||
|
||||
class BigmemPickleTests:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue