cpython: ed0c05c739c9 (original) (raw)
Mercurial > cpython
changeset 106428:ed0c05c739c9 3.6
Issue #28164: Correctly handle special console filenames (patch by Eryk Sun) [#28164]
Steve Dower steve.dower@microsoft.com | |
---|---|
date | Sat, 04 Feb 2017 15:07:46 -0800 |
parents | 0bf72810f8ea |
children | a5538734cc87 54fea351e3f9 |
files | Lib/test/test_winconsoleio.py Misc/NEWS Modules/_io/winconsoleio.c |
diffstat | 3 files changed, 76 insertions(+), 21 deletions(-)[+] [-] Lib/test/test_winconsoleio.py 28 Misc/NEWS 2 Modules/_io/winconsoleio.c 67 |
line wrap: on
line diff
--- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -1,9 +1,11 @@ '''Tests for WindowsConsoleIO ''' +import os import io +import sys import unittest -import sys +import tempfile if sys.platform != 'win32': raise unittest.SkipTest("test only relevant on win32") @@ -19,6 +21,16 @@ class WindowsConsoleIOTests(unittest.Tes self.assertFalse(issubclass(ConIO, io.TextIOBase)) def test_open_fd(self):
self.assertRaisesRegex(ValueError,[](#l1.20)
"negative file descriptor", ConIO, -1)[](#l1.21)
fd, _ = tempfile.mkstemp()[](#l1.23)
try:[](#l1.24)
self.assertRaisesRegex(ValueError,[](#l1.25)
"Cannot open non-console file", ConIO, fd)[](#l1.26)
finally:[](#l1.27)
os.close(fd)[](#l1.28)
+ try: f = ConIO(0) except ValueError: @@ -56,6 +68,20 @@ class WindowsConsoleIOTests(unittest.Tes f.close() def test_open_name(self):
self.assertRaises(ValueError, ConIO, sys.executable)[](#l1.37)
f = open('C:/con', 'rb', buffering=0)[](#l1.39)
self.assertIsInstance(f, ConIO)[](#l1.40)
f.close()[](#l1.41)
f = open(r'\\.\conin$', 'rb', buffering=0)[](#l1.43)
self.assertIsInstance(f, ConIO)[](#l1.44)
f.close()[](#l1.45)
f = open('//?/conout$', 'wb', buffering=0)[](#l1.47)
self.assertIsInstance(f, ConIO)[](#l1.48)
f.close()[](#l1.49)
+ f = ConIO("CON") self.assertTrue(f.readable()) self.assertFalse(f.writable())
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -146,6 +146,8 @@ Library Windows ------- +- Issue #28164: Correctly handle special console filenames (patch by Eryk Sun) +
- Issue #29409: Implement PEP 529 for io.FileIO (Patch by Eryk Sun)
- Issue #29392: Prevent crash when passing invalid arguments into msvcrt module.
--- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -60,51 +60,68 @@ char _get_console_type(HANDLE handle) { } char _PyIO_get_console_type(PyObject *path_or_fd) {
- int fd = PyLong_AsLong(path_or_fd); PyErr_Clear(); if (fd >= 0) { HANDLE handle; _Py_BEGIN_SUPPRESS_IPH handle = (HANDLE)_get_osfhandle(fd); _Py_END_SUPPRESS_IPH
if (!handle)[](#l3.17)
}if (handle == INVALID_HANDLE_VALUE)[](#l3.18) return '\0';[](#l3.19) return _get_console_type(handle);[](#l3.20)
- if (!PyUnicode_Check(decoded)) {
Py_CLEAR(decoded);[](#l3.34)
return '\0';[](#l3.35)
- }
- decoded_upper = PyObject_CallMethod(decoded, "upper", "");
- if (!decoded_wstr) { PyErr_Clear(); return '\0'; }
- DWORD length;
- wchar_t name_buf[MAX_PATH], *pname_buf = name_buf;
- length = GetFullPathNameW(decoded_wstr, MAX_PATH, pname_buf, NULL);
- if (length > MAX_PATH) {
pname_buf = PyMem_New(wchar_t, length);[](#l3.51)
if (pname_buf)[](#l3.52)
length = GetFullPathNameW(decoded_wstr, length, pname_buf, NULL);[](#l3.53)
else[](#l3.54)
length = 0;[](#l3.55)
- }
- PyMem_Free(decoded_wstr);
- if (_PyUnicode_EqualToASCIIString(decoded_upper, "CONIN$")) {
m = 'r';[](#l3.61)
- } else if (_PyUnicode_EqualToASCIIString(decoded_upper, "CONOUT$")) {
m = 'w';[](#l3.63)
- } else if (_PyUnicode_EqualToASCIIString(decoded_upper, "CON")) {
m = 'x';[](#l3.65)
- if (length) {
wchar_t *name = pname_buf;[](#l3.67)
if (length >= 4 && name[3] == L'\\' &&[](#l3.68)
(name[2] == L'.' || name[2] == L'?') &&[](#l3.69)
name[1] == L'\\' && name[0] == L'\\') {[](#l3.70)
name += 4;[](#l3.71)
}[](#l3.72)
if (!_wcsicmp(name, L"CONIN$")) {[](#l3.73)
m = 'r';[](#l3.74)
} else if (!_wcsicmp(name, L"CONOUT$")) {[](#l3.75)
m = 'w';[](#l3.76)
} else if (!_wcsicmp(name, L"CON")) {[](#l3.77)
m = 'x';[](#l3.78)
}}[](#l3.79)
- if (pname_buf != name_buf)
return m; } + /*[clinic input] module _io class _io._WindowsConsoleIO "winconsoleio *" "&PyWindowsConsoleIO_Type" @@ -289,6 +306,11 @@ static int Py_CLEAR(decodedname); if (name == NULL) return -1;PyMem_Free(pname_buf);[](#l3.84)
if (console_type == '\0') {[](#l3.96)
PyErr_SetString(PyExc_ValueError,[](#l3.97)
"Cannot open non-console file");[](#l3.98)
return -1;[](#l3.99)
}[](#l3.100)
if (wcslen(name) != length) { PyMem_Free(name); @@ -370,6 +392,11 @@ static int if (console_type == '\0') console_type = _get_console_type(self->handle);