diff options
author | Guido van Rossum <guido@python.org> | 1997-08-20 22:26:19 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1997-08-20 22:26:19 (GMT) |
commit | 558be283bf2c3a2c405c8a404da1cfed69900226 (patch) | |
tree | 10459fb7fd83a7ad78ba35c6b458e41cb00c1010 | |
parent | 86c052e83afc980d105186d53473210bb425e2ae (diff) | |
download | cpython-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.py | 18 |
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) |