]> granicus.if.org Git - python/commitdiff
Issue #27512: Don't segfault when os.fspath() calls an object whose
authorBrett Cannon <brett@python.org>
Fri, 15 Jul 2016 17:41:49 +0000 (10:41 -0700)
committerBrett Cannon <brett@python.org>
Fri, 15 Jul 2016 17:41:49 +0000 (10:41 -0700)
__fspath__() raises an exception.

Thanks to Xiang Zhang for the patch.

Lib/test/test_os.py
Misc/NEWS
Modules/posixmodule.c

index 4ade4aa9db48f3182d0339baa05843378d896dec..ecd2efb0e9a830c488005e23c30c3cac1f372277 100644 (file)
@@ -3122,7 +3122,10 @@ class TestPEP519(unittest.TestCase):
         def __init__(self, path=''):
             self.path = path
         def __fspath__(self):
-            return self.path
+            if isinstance(self.path, BaseException):
+                raise self.path
+            else:
+                return self.path
 
     def test_return_bytes(self):
         for b in b'hello', b'goodbye', b'some/path/and/file':
@@ -3145,18 +3148,25 @@ class TestPEP519(unittest.TestCase):
         self.assertTrue(issubclass(self.PathLike, os.PathLike))
         self.assertTrue(isinstance(self.PathLike(), os.PathLike))
 
-        with self.assertRaises(TypeError):
-            self.fspath(self.PathLike(42))
-
     def test_garbage_in_exception_out(self):
         vapor = type('blah', (), {})
         for o in int, type, os, vapor():
             self.assertRaises(TypeError, self.fspath, o)
 
     def test_argument_required(self):
-        with self.assertRaises(TypeError):
-            self.fspath()
-
+        self.assertRaises(TypeError, self.fspath)
+
+    def test_bad_pathlike(self):
+        # __fspath__ returns a value other than str or bytes.
+        self.assertRaises(TypeError, self.fspath, self.PathLike(42))
+        # __fspath__ attribute that is not callable.
+        c = type('foo', (), {})
+        c.__fspath__ = 1
+        self.assertRaises(TypeError, self.fspath, c())
+        # __fspath__ raises an exception.
+        c.__fspath__ = lambda self: self.__not_exist
+        self.assertRaises(ZeroDivisionError, self.fspath,
+                          self.PathLike(ZeroDivisionError))
 
 # Only test if the C version is provided, otherwise TestPEP519 already tested
 # the pure Python implementation.
index de7c09c3c98e930d622a981d6a2226d06a7715d6..e3d01ba6561b33ddb024826b4d25a63b6a29e92e 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -16,6 +16,9 @@ Core and Builtins
 Library
 -------
 
+- Issue 27512: Fix a segfault when os.fspath() called a an __fspath__() method
+  that raised an exception. Patch by Xiang Zhang.
+
 Tests
 -----
 
index 4c0f26e89c1e6af8af977b909cdb034dbb8a43d7..7f16a83e788c4a5927a66ea5a6d490e6019f7062 100644 (file)
@@ -12319,6 +12319,10 @@ PyOS_FSPath(PyObject *path)
 
     path_repr = PyObject_CallFunctionObjArgs(func, NULL);
     Py_DECREF(func);
+    if (NULL == path_repr) {
+        return NULL;
+    }
+
     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
         PyErr_Format(PyExc_TypeError,
                      "expected %.200s.__fspath__() to return str or bytes, "