summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1997-08-20 22:26:19 (GMT)
committerGuido van Rossum <guido@python.org>1997-08-20 22:26:19 (GMT)
commit558be283bf2c3a2c405c8a404da1cfed69900226 (patch)
tree10459fb7fd83a7ad78ba35c6b458e41cb00c1010
parent86c052e83afc980d105186d53473210bb425e2ae (diff)
downloadcpython-558be283bf2c3a2c405c8a404da1cfed69900226.zip
cpython-558be283bf2c3a2c405c8a404da1cfed69900226.tar.gz
cpython-558be283bf2c3a2c405c8a404da1cfed69900226.tar.bz2
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.)
-rw-r--r--Lib/copy.py18
1 files changed, 18 insertions, 0 deletions
diff --git a/Lib/copy.py b/Lib/copy.py
index 6dc781c..ef5b10e 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -195,11 +195,28 @@ def _deepcopy_dict(x, memo):
return y
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):
if hasattr(x, '__deepcopy__'):
return x.__deepcopy__()
if hasattr(x, '__getinitargs__'):
args = x.__getinitargs__()
+ _keep_alive(args, memo)
args = deepcopy(args, memo)
else:
args = ()
@@ -207,6 +224,7 @@ def _deepcopy_inst(x, memo):
memo[id(x)] = y
if hasattr(x, '__getstate__'):
state = x.__getstate__()
+ _keep_alive(state, memo)
else:
state = x.__dict__
state = deepcopy(state, memo)