[Python-checkins] cpython: Fix uninitialized variable after #22676.

antoine.pitrou python-checkins at python.org
Tue Dec 2 00:20:28 CET 2014


https://hg.python.org/cpython/rev/3e3bec66409c
changeset:   93696:3e3bec66409c
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Tue Dec 02 00:20:03 2014 +0100
summary:
  Fix uninitialized variable after #22676.

files:
  Lib/test/pickletester.py |  21 +++++++++++++++++++++
  Modules/_pickle.c        |  24 +++++++++++++++++-------
  2 files changed, 38 insertions(+), 7 deletions(-)


diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -1636,6 +1636,27 @@
                     unpickled = self.loads(self.dumps(method, proto))
                     self.assertEqual(method(*args), unpickled(*args))
 
+    def test_local_lookup_error(self):
+        # Test that whichmodule() errors out cleanly when looking up
+        # an assumed globally-reachable object fails.
+        def f():
+            pass
+        # Since the function is local, lookup will fail
+        for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
+            with self.assertRaises((AttributeError, pickle.PicklingError)):
+                pickletools.dis(self.dumps(f, proto))
+        # Same without a __module__ attribute (exercises a different path
+        # in _pickle.c).
+        del f.__module__
+        for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
+            with self.assertRaises((AttributeError, pickle.PicklingError)):
+                pickletools.dis(self.dumps(f, proto))
+        # Yet a different path.
+        f.__name__ = f.__qualname__
+        for proto in range(0, pickle.HIGHEST_PROTOCOL + 1):
+            with self.assertRaises((AttributeError, pickle.PicklingError)):
+                pickletools.dis(self.dumps(f, proto))
+
 
 class BigmemPickleTests(unittest.TestCase):
 
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -1547,10 +1547,16 @@
     n = PyList_GET_SIZE(dotted_path);
     assert(n >= 1);
     if (!allow_qualname && n > 1) {
-        PyErr_Format(PyExc_AttributeError,
-                     "Can't get qualified attribute %R on %R;"
-                     "use protocols >= 4 to enable support",
-                     name, obj);
+        if (obj == NULL)
+            PyErr_Format(PyExc_AttributeError,
+                         "Can't pickle qualified object %R; "
+                         "use protocols >= 4 to enable support",
+                         name);
+        else
+            PyErr_Format(PyExc_AttributeError,
+                         "Can't pickle qualified attribute %R on %R; "
+                         "use protocols >= 4 to enable support",
+                         name, obj);
         Py_DECREF(dotted_path);
         return NULL;
     }
@@ -1562,8 +1568,12 @@
         assert(PyBool_Check(result));
         Py_DECREF(result);
         if (is_equal) {
-            PyErr_Format(PyExc_AttributeError,
-                         "Can't get local attribute %R on %R", name, obj);
+            if (obj == NULL)
+                PyErr_Format(PyExc_AttributeError,
+                             "Can't pickle local object %R", name);
+            else
+                PyErr_Format(PyExc_AttributeError,
+                             "Can't pickle local attribute %R on %R", name, obj);
             Py_DECREF(dotted_path);
             return NULL;
         }
@@ -1653,7 +1663,7 @@
         return NULL;
     }
 
-    dotted_path = get_dotted_path(module, global_name, allow_qualname);
+    dotted_path = get_dotted_path(NULL, global_name, allow_qualname);
     if (dotted_path == NULL)
         return NULL;
 

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


More information about the Python-checkins mailing list