changeset: 91549:bd6515070f9c parent: 91547:f79f0967537f parent: 91548:758468cdf72c user: Antoine Pitrou date: Fri Jul 04 20:26:22 2014 -0400 files: Misc/NEWS description: Issue #21897: Fix a crash with the f_locals attribute with closure variables when frame.clear() has been called. diff -r f79f0967537f -r bd6515070f9c Lib/test/test_frame.py --- a/Lib/test/test_frame.py Fri Jul 04 17:17:57 2014 -0700 +++ b/Lib/test/test_frame.py Fri Jul 04 20:26:22 2014 -0400 @@ -1,5 +1,6 @@ import gc import sys +import types import unittest import weakref @@ -109,6 +110,57 @@ self.assertIs(None, wr()) +class FrameLocalsTest(unittest.TestCase): + """ + Tests for the .f_locals attribute. + """ + + def make_frames(self): + def outer(): + x = 5 + y = 6 + def inner(): + z = x + 2 + 1/0 + t = 9 + return inner() + try: + outer() + except ZeroDivisionError as e: + tb = e.__traceback__ + frames = [] + while tb: + frames.append(tb.tb_frame) + tb = tb.tb_next + return frames + + def test_locals(self): + f, outer, inner = self.make_frames() + outer_locals = outer.f_locals + self.assertIsInstance(outer_locals.pop('inner'), types.FunctionType) + self.assertEqual(outer_locals, {'x': 5, 'y': 6}) + inner_locals = inner.f_locals + self.assertEqual(inner_locals, {'x': 5, 'z': 7}) + + def test_clear_locals(self): + # Test f_locals after clear() (issue #21897) + f, outer, inner = self.make_frames() + outer.clear() + inner.clear() + self.assertEqual(outer.f_locals, {}) + self.assertEqual(inner.f_locals, {}) + + def test_locals_clear_locals(self): + # Test f_locals before and after clear() (to exercise caching) + f, outer, inner = self.make_frames() + outer.f_locals + inner.f_locals + outer.clear() + inner.clear() + self.assertEqual(outer.f_locals, {}) + self.assertEqual(inner.f_locals, {}) + + def test_main(): support.run_unittest(__name__) diff -r f79f0967537f -r bd6515070f9c Misc/NEWS --- a/Misc/NEWS Fri Jul 04 17:17:57 2014 -0700 +++ b/Misc/NEWS Fri Jul 04 20:26:22 2014 -0400 @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #21897: Fix a crash with the f_locals attribute with closure + variables when frame.clear() has been called. + - Issue #21205: Add a new ``__qualname__`` attribute to generator, the qualified name, and use it in the representation of a generator (``repr(gen)``). The default name of the generator (``__name__`` attribute) diff -r f79f0967537f -r bd6515070f9c Objects/frameobject.c --- a/Objects/frameobject.c Fri Jul 04 17:17:57 2014 -0700 +++ b/Objects/frameobject.c Fri Jul 04 20:26:22 2014 -0400 @@ -786,7 +786,7 @@ PyObject *key = PyTuple_GET_ITEM(map, j); PyObject *value = values[j]; assert(PyUnicode_Check(key)); - if (deref) { + if (deref && value != NULL) { assert(PyCell_Check(value)); value = PyCell_GET(value); }