Index: Lib/test/crashers/gc_inspection.py =================================================================== --- Lib/test/crashers/gc_inspection.py (revision 47245) +++ Lib/test/crashers/gc_inspection.py (working copy) @@ -1,17 +1,68 @@ """ gc.get_referrers() can be used to see objects before they are fully built. + +The problem stems from pre-allocating a tuple, then filling it by calling +user-defined code. Once the user has control again, gc.get_referrers() can +be used to grab the pre-allocated tuple; all you have to do then is try to +use an unfilled tuple index to crash the interpreter. + +The following test cases indicate places where this behaviour has been found. """ import gc +import os +def test_tuple(): + def g(): + marker = object() + yield marker + # now the marker is in the tuple being constructed + referrers = [x for x in gc.get_referrers(marker) if type(x) is tuple] + if referrers: + print referrers[0] + print referrers[0][1] -def g(): - marker = object() - yield marker - # now the marker is in the tuple being constructed - [tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple] - print tup - print tup[1] + tuple(g()) + +def test_filter(): + """ + Bug report: python.org/sf/1517663 + """ + class BadSeq(tuple): + def __getitem__(self, index): + if index == 0: + self.marker = object() + return self.marker + referrers = [x for x in gc.get_referrers(self.marker) if type(x) is tuple] + if referrers: + print referrers[0] + print referrers[0][1] -tuple(g()) + filter(None, BadSeq([5, 6, 7, 9, 10])) + +results = [] +for test_func in [test_tuple, test_filter]: + print "### Starting", test_func.__name__ + print "#################################" + + child_id = os.fork() + if child_id: + (pid, status) = os.waitpid(child_id, 0) + + if status: + results.append(test_func.__name__ + " failed") + else: + results.append(test_func.__name__ + " passed") + + # Add some whitespace to make things legible + print + print + else: + test_func() + print test_func.__name__, "passed" + raise SystemExit() + +for res in results: + print res +