summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_os.py
diff options
context:
space:
mode:
authorMark Becwar <mark@thebecwar.com>2019-02-02 21:08:23 (GMT)
committerSteve Dower <steve.dower@microsoft.com>2019-02-02 21:08:23 (GMT)
commitb82bfac4369c0429e562a834b3752e66c4821eab (patch)
tree24cb35ba11a8bd4e00d69b38081b85e17d4ebd31 /Lib/test/test_os.py
parentcb0904762681031edc50f9d7d7ef48cffcf96d9a (diff)
downloadcpython-b82bfac4369c0429e562a834b3752e66c4821eab.zip
cpython-b82bfac4369c0429e562a834b3752e66c4821eab.tar.gz
cpython-b82bfac4369c0429e562a834b3752e66c4821eab.tar.bz2
bpo-29734: nt._getfinalpathname handle leak (GH-740)
Make sure that failure paths call CloseHandle outside of the function that failed
Diffstat (limited to 'Lib/test/test_os.py')
-rw-r--r--Lib/test/test_os.py56
1 files changed, 56 insertions, 0 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index aca445f..9e0bef5 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -2325,6 +2325,62 @@ class Win32JunctionTests(unittest.TestCase):
os.unlink(self.junction)
self.assertFalse(os.path.exists(self.junction))
+@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
+class Win32NtTests(unittest.TestCase):
+ def setUp(self):
+ from test import support
+ self.nt = support.import_module('nt')
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_getfinalpathname_handles(self):
+ try:
+ import ctypes, ctypes.wintypes
+ except ImportError:
+ raise unittest.SkipTest('ctypes module is required for this test')
+
+ kernel = ctypes.WinDLL('Kernel32.dll', use_last_error=True)
+ kernel.GetCurrentProcess.restype = ctypes.wintypes.HANDLE
+
+ kernel.GetProcessHandleCount.restype = ctypes.wintypes.BOOL
+ kernel.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE,
+ ctypes.wintypes.LPDWORD)
+
+ # This is a pseudo-handle that doesn't need to be closed
+ hproc = kernel.GetCurrentProcess()
+
+ handle_count = ctypes.wintypes.DWORD()
+ ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
+ self.assertEqual(1, ok)
+
+ before_count = handle_count.value
+
+ # The first two test the error path, __file__ tests the success path
+ filenames = [ r'\\?\C:',
+ r'\\?\NUL',
+ r'\\?\CONIN',
+ __file__ ]
+
+ for i in range(10):
+ for name in filenames:
+ try:
+ tmp = self.nt._getfinalpathname(name)
+ except:
+ # Failure is expected
+ pass
+ try:
+ tmp = os.stat(name)
+ except:
+ pass
+
+ ok = kernel.GetProcessHandleCount(hproc, ctypes.byref(handle_count))
+ self.assertEqual(1, ok)
+
+ handle_delta = handle_count.value - before_count
+
+ self.assertEqual(0, handle_delta)
@support.skip_unless_symlink
class NonLocalSymlinkTests(unittest.TestCase):