[Python-checkins] cpython (3.4): Issue #21897: Fix a crash with the f_locals attribute with closure variables

antoine.pitrou python-checkins at python.org
Sat Jul 5 02:30:39 CEST 2014


http://hg.python.org/cpython/rev/758468cdf72c
changeset:   91548:758468cdf72c
branch:      3.4
parent:      91546:888fd1cdec6f
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Fri Jul 04 20:24:13 2014 -0400
summary:
  Issue #21897: Fix a crash with the f_locals attribute with closure variables when frame.clear() has been called.

files:
  Lib/test/test_frame.py |  52 ++++++++++++++++++++++++++++++
  Misc/NEWS              |   3 +
  Objects/frameobject.c  |   2 +-
  3 files changed, 56 insertions(+), 1 deletions(-)


diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py
--- a/Lib/test/test_frame.py
+++ b/Lib/test/test_frame.py
@@ -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 --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,9 @@
 Library
 -------
 
+- Issue #21897: Fix a crash with the f_locals attribute with closure
+  variables when frame.clear() has been called.
+
 - Issue #21151: Fixed a segfault in the winreg module when ``None`` is passed
   as a ``REG_BINARY`` value to SetValueEx.  Patch by John Ehresman.
 
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -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);
         }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list