]> granicus.if.org Git - python/commitdiff
Make sure the objects returned by __getinitargs__() are kept alive (in
authorGuido van Rossum <guido@python.org>
Wed, 20 Aug 1997 22:26:19 +0000 (22:26 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 20 Aug 1997 22:26:19 +0000 (22:26 +0000)
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.)

Lib/copy.py

index 6dc781c4e06a1ffe509abffe13fbb212c5409760..ef5b10edd04b07f386a51992223e8eea4bb0a8be 100644 (file)
@@ -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)