]> granicus.if.org Git - python/commitdiff
Fix uninitialized variable after #22676.
authorAntoine Pitrou <solipsis@pitrou.net>
Mon, 1 Dec 2014 23:20:03 +0000 (00:20 +0100)
committerAntoine Pitrou <solipsis@pitrou.net>
Mon, 1 Dec 2014 23:20:03 +0000 (00:20 +0100)
Lib/test/pickletester.py
Modules/_pickle.c

index 5963175ddd1565602345b8e3c9228a948de3a6fb..021adcc408dbebdfd2948b3049957152287dea19 100644 (file)
@@ -1636,6 +1636,27 @@ class AbstractPickleTests(unittest.TestCase):
                     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):
 
index a13eff32c3fff6a4249af6c9be7261e9d0d72c9d..ecf0c6ca9533c73f30a51f9703ae67e542e497ca 100644 (file)
@@ -1547,10 +1547,16 @@ get_dotted_path(PyObject *obj, PyObject *name, int allow_qualname) {
     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 @@ get_dotted_path(PyObject *obj, PyObject *name, int allow_qualname) {
         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 @@ whichmodule(PyObject *global, PyObject *global_name, int allow_qualname)
         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;