]> granicus.if.org Git - python/commitdiff
Issue #15261: Stop os.stat(fd) crashing on Windows when fd not open.
authorRichard Oudkerk <shibturn@gmail.com>
Fri, 6 Jul 2012 11:05:32 +0000 (12:05 +0100)
committerRichard Oudkerk <shibturn@gmail.com>
Fri, 6 Jul 2012 11:05:32 +0000 (12:05 +0100)
Doc/library/os.path.rst
Lib/test/test_genericpath.py
Lib/test/test_os.py
Misc/NEWS
Modules/posixmodule.c

index 782162866d4515bcea0f7e81ebf269de1f0d5b4c..20a84b618a37df2f61063e78551397095da0d065 100644 (file)
@@ -70,11 +70,16 @@ applications should use string objects to access all files.
 
 .. function:: exists(path)
 
-   Return ``True`` if *path* refers to an existing path.  Returns ``False`` for
-   broken symbolic links. On some platforms, this function may return ``False`` if
-   permission is not granted to execute :func:`os.stat` on the requested file, even
+   Return ``True`` if *path* refers to an existing path or an open
+   file descriptor.  Returns ``False`` for broken symbolic links.  On
+   some platforms, this function may return ``False`` if permission is
+   not granted to execute :func:`os.stat` on the requested file, even
    if the *path* physically exists.
 
+   .. versionchanged:: 3.3
+      *path* can now be an integer: ``True`` is returned if it is an
+       open file descriptor, ``False`` otherwise.
+
 
 .. function:: lexists(path)
 
index ebb8396f186daa531734e50dff8d87024bcfc726..fc3d44c589e40c8bd28c0fbc77ce840301b03bff 100644 (file)
@@ -146,6 +146,16 @@ class GenericTest(unittest.TestCase):
                 f.close()
             support.unlink(support.TESTFN)
 
+    @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
+    def test_exists_fd(self):
+        r, w = os.pipe()
+        try:
+            self.assertTrue(self.pathmodule.exists(r))
+        finally:
+            os.close(r)
+            os.close(w)
+        self.assertFalse(self.pathmodule.exists(r))
+
     def test_isdir(self):
         self.assertIs(self.pathmodule.isdir(support.TESTFN), False)
         f = open(support.TESTFN, "wb")
index 57de993319ba6e1cc4c1fd7547d09bbe4c223f23..7c73f1e1aa01fc0e690e17529f9b8483dd54e9e4 100644 (file)
@@ -473,6 +473,19 @@ class StatAttributeTests(unittest.TestCase):
                     return
                 self.fail("Could not stat pagefile.sys")
 
+        @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
+        def test_15261(self):
+            # Verify that stat'ing a closed fd does not cause crash
+            r, w = os.pipe()
+            try:
+                os.stat(r)          # should not raise error
+            finally:
+                os.close(r)
+                os.close(w)
+            with self.assertRaises(OSError) as ctx:
+                os.stat(r)
+            self.assertEqual(ctx.exception.errno, errno.EBADF)
+
 from test import mapping_tests
 
 class EnvironTests(mapping_tests.BasicTestMappingProtocol):
index a78f72b0791a26658aab88fa717ac82c8b7ae968..19488dcd005fb753a5c268da2b0a1d08a66ef0dd 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -23,6 +23,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #15261: Stop os.stat(fd) crashing on Windows when fd not open.
+
 - Issue #15166: Implement imp.get_tag() using sys.implementation.cache_tag.
 
 - Issue #15210: Catch KeyError when imprortlib.__init__ can't find
index 1bd5e97d7b754eba35fbfef874070cd97a590854..b99a5fe01e50f7cb65be565fcf8e32ada5558b95 100644 (file)
@@ -1829,7 +1829,10 @@ win32_fstat(int file_number, struct win32_stat *result)
     HANDLE h;
     int type;
 
-    h = (HANDLE)_get_osfhandle(file_number);
+    if (!_PyVerify_fd(file_number))
+        h = INVALID_HANDLE_VALUE;
+    else
+        h = (HANDLE)_get_osfhandle(file_number);
 
     /* Protocol violation: we explicitly clear errno, instead of
        setting it to a POSIX error. Callers should use GetLastError. */
@@ -8244,8 +8247,6 @@ posix_fstat(PyObject *self, PyObject *args)
     /* on OpenVMS we must ensure that all bytes are written to the file */
     fsync(fd);
 #endif
-    if (!_PyVerify_fd(fd))
-        return posix_error();
     Py_BEGIN_ALLOW_THREADS
     res = FSTAT(fd, &st);
     Py_END_ALLOW_THREADS