mirror of
https://github.com/python/cpython.git
synced 2025-12-09 02:35:14 +00:00
Make sure the objects returned by __getinitargs__() are kept alive (in
the memo) to avoid a certain kind of nasty crash. (Not easily reproducable because it requires a later call to __getinitargs__() to return a tuple that happens to be allocated at the same address.)
This commit is contained in:
parent
86c052e83a
commit
558be283bf
1 changed files with 18 additions and 0 deletions
18
Lib/copy.py
18
Lib/copy.py
|
|
@ -195,11 +195,28 @@ def _deepcopy_dict(x, memo):
|
||||||
return y
|
return y
|
||||||
d[types.DictionaryType] = _deepcopy_dict
|
d[types.DictionaryType] = _deepcopy_dict
|
||||||
|
|
||||||
|
def _keep_alive(x, memo):
|
||||||
|
"""Keeps a reference to the object x in the memo.
|
||||||
|
|
||||||
|
Because we remember objects by their id, we have
|
||||||
|
to assure that possibly temporary objects are kept
|
||||||
|
alive by referencing them.
|
||||||
|
We store a reference at the id of the memo, which should
|
||||||
|
normally not be used unless someone tries to deepcopy
|
||||||
|
the memo itself...
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
memo[id(memo)].append(x)
|
||||||
|
except KeyError:
|
||||||
|
# aha, this is the first one :-)
|
||||||
|
memo[id(memo)]=[x]
|
||||||
|
|
||||||
def _deepcopy_inst(x, memo):
|
def _deepcopy_inst(x, memo):
|
||||||
if hasattr(x, '__deepcopy__'):
|
if hasattr(x, '__deepcopy__'):
|
||||||
return x.__deepcopy__()
|
return x.__deepcopy__()
|
||||||
if hasattr(x, '__getinitargs__'):
|
if hasattr(x, '__getinitargs__'):
|
||||||
args = x.__getinitargs__()
|
args = x.__getinitargs__()
|
||||||
|
_keep_alive(args, memo)
|
||||||
args = deepcopy(args, memo)
|
args = deepcopy(args, memo)
|
||||||
else:
|
else:
|
||||||
args = ()
|
args = ()
|
||||||
|
|
@ -207,6 +224,7 @@ def _deepcopy_inst(x, memo):
|
||||||
memo[id(x)] = y
|
memo[id(x)] = y
|
||||||
if hasattr(x, '__getstate__'):
|
if hasattr(x, '__getstate__'):
|
||||||
state = x.__getstate__()
|
state = x.__getstate__()
|
||||||
|
_keep_alive(state, memo)
|
||||||
else:
|
else:
|
||||||
state = x.__dict__
|
state = x.__dict__
|
||||||
state = deepcopy(state, memo)
|
state = deepcopy(state, memo)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue