# HG changeset patch # User Steve Dower # Date 1424930096 28800 # Wed Feb 25 21:54:56 2015 -0800 # Node ID 6de0462e1d069ce0ad877bbf5fa9dfb9635e4490 # Parent 99eb196fb345c07f0bc7a7c438209bf3c435eb4f Issue #23524: Replace _PyVerify_fd function with calls to _set_thread_local_invalid_parameter_handler. diff --git a/Include/fileutils.h b/Include/fileutils.h --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -122,7 +122,7 @@ PyAPI_FUNC(int) _Py_set_blocking(int fd, int blocking); #endif /* !MS_WINDOWS */ -#if defined _MSC_VER && _MSC_VER >= 1400 +#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 /* A routine to check if a file descriptor is valid on Windows. Returns 0 * and sets errno to EBADF if it isn't. This is to avoid Assertions * from various functions in the Windows CRT beginning with diff --git a/Include/pymacro.h b/Include/pymacro.h --- a/Include/pymacro.h +++ b/Include/pymacro.h @@ -88,4 +88,24 @@ #define Py_UNUSED(name) _unused_ ## name #endif +#ifdef Py_BUILD_CORE +/* + * Macros to protect CRT calls against instant termination when passed an + * invalid parameter (issue23524). + */ +#if defined _MSC_VER && _MSC_VER >= 1900 + +PyAPI_DATA(void*) _Py_silent_invalid_parameter_handler; +#define _Py_BEGIN_SUPPRESS_IPH { _invalid_parameter_handler _Py_old_handler = \ + _set_thread_local_invalid_parameter_handler((_invalid_parameter_handler)_Py_silent_invalid_parameter_handler); +#define _Py_END_SUPPRESS_IPH _set_thread_local_invalid_parameter_handler(_Py_old_handler); } + +#else + +#define _Py_BEGIN_SUPPRESS_IPH +#define _Py_END_SUPPRESS_IPH + +#endif /* _MSC_VER >= 1900 */ +#endif /* Py_BUILD_CORE */ + #endif /* Py_PYMACRO_H */ diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -107,9 +107,11 @@ /* fd is accessible and someone else may have closed it */ if (_PyVerify_fd(fd)) { Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH err = close(fd); if (err < 0) save_errno = errno; + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } else { save_errno = errno; @@ -182,13 +184,7 @@ { #if defined(HAVE_FSTAT) || defined(MS_WINDOWS) struct _Py_stat_struct buf; - if (_Py_fstat(fd, &buf) < 0 && -#ifdef MS_WINDOWS - GetLastError() == ERROR_INVALID_HANDLE -#else - errno == EBADF -#endif - ) { + if (_Py_fstat(fd, &buf) < 0 && errno == EBADF) { PyObject *exc; char *msg = strerror(EBADF); exc = PyObject_CallFunction(PyExc_OSError, "(is)", @@ -633,11 +629,14 @@ if (!_PyVerify_fd(self->fd)) return PyErr_SetFromErrno(PyExc_IOError); + _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS pos = _lseeki64(self->fd, 0L, SEEK_CUR); #else pos = lseek(self->fd, 0L, SEEK_CUR); #endif + _Py_END_SUPPRESS_IPH + if (_Py_fstat(self->fd, &st) == 0) end = st.st_size; else @@ -838,11 +837,13 @@ if (_PyVerify_fd(fd)) { Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS res = _lseeki64(fd, pos, whence); #else res = lseek(fd, pos, whence); #endif + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } else res = -1; @@ -1043,7 +1044,12 @@ if (self->fd < 0) return err_closed(); Py_BEGIN_ALLOW_THREADS - res = isatty(self->fd); + _Py_BEGIN_SUPPRESS_IPH + if (_PyVerify_fd(self->fd)) + res = isatty(self->fd); + else + res = 0; + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS return PyBool_FromLong(res); } diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1330,11 +1330,13 @@ */ if (fileno != -1 && fileno != 0) { /* Ensure that fileno is within the CRT's valid range */ - if (_PyVerify_fd(fileno) == 0) { + if (!_PyVerify_fd(fileno)) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } + _Py_BEGIN_SUPPRESS_IPH fh = (HANDLE)_get_osfhandle(fileno); + _Py_END_SUPPRESS_IPH if (fh==(HANDLE)-1) { PyErr_SetFromErrno(PyExc_OSError); return NULL; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1280,10 +1280,6 @@ fd = PyObject_AsFileDescriptor(o); if (fd < 0) return 0; - if (!_PyVerify_fd(fd)) { - posix_error(); - return 0; - } *pointer = fd; return 1; } @@ -1294,9 +1290,14 @@ int res; int async_err = 0; + if (!_PyVerify_fd(fd)) + return posix_error(); + do { Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH res = (*func)(fd); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); if (res != 0) @@ -5685,6 +5686,7 @@ int result; Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS if (path->wide) result = Py_DeleteFileW(path->wide); @@ -5699,6 +5701,7 @@ #endif /* HAVE_UNLINKAT */ result = unlink(path->narrow); #endif + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (result) @@ -10693,6 +10696,7 @@ do { Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS if (path->wide) fd = _wopen(path->wide, flags, mode); @@ -10773,7 +10777,9 @@ * for more details. */ Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH res = close(fd); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (res < 0) return posix_error(); @@ -10826,9 +10832,11 @@ { int i; Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH for (i = fd_low; i < fd_high; i++) if (_PyVerify_fd(i)) close(i); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS Py_RETURN_NONE; } @@ -10943,7 +10951,9 @@ */ #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH res = dup2(fd, fd2); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (res < 0) return posix_error(); @@ -11151,11 +11161,13 @@ return -1; } Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS result = _lseeki64(fd, position, how); #else result = lseek(fd, position, how); #endif + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (result < 0) posix_error(); @@ -11465,7 +11477,9 @@ do { Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); @@ -11617,6 +11631,7 @@ #else ret = sendfile(in, out, offset, len, &sf, &sbytes, flags); #endif + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); @@ -11802,9 +11817,13 @@ os_isatty_impl(PyModuleDef *module, int fd) /*[clinic end generated code: output=4bfadbfe22715097 input=08ce94aa1eaf7b5e]*/ { + int return_value; if (!_PyVerify_fd(fd)) return 0; - return isatty(fd); + _Py_BEGIN_SUPPRESS_IPH + return_value = isatty(fd); + _Py_END_SUPPRESS_IPH + return return_value; } @@ -12132,7 +12151,9 @@ do { Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); @@ -16093,12 +16114,16 @@ os_get_inheritable_impl(PyModuleDef *module, int fd) /*[clinic end generated code: output=261d1dd2b0dbdc35 input=89ac008dc9ab6b95]*/ { - if (!_PyVerify_fd(fd)){ + int return_value; + if (!_PyVerify_fd(fd)) { posix_error(); return -1; } - return _Py_get_inheritable(fd); + _Py_BEGIN_SUPPRESS_IPH + return_value = _Py_get_inheritable(fd); + _Py_END_SUPPRESS_IPH + return return_value; } @@ -16144,10 +16169,14 @@ os_set_inheritable_impl(PyModuleDef *module, int fd, int inheritable) /*[clinic end generated code: output=64dfe5e15c906539 input=9ceaead87a1e2402]*/ { + int result; if (!_PyVerify_fd(fd)) return posix_error(); - if (_Py_set_inheritable(fd, inheritable, NULL) < 0) + _Py_BEGIN_SUPPRESS_IPH + result = _Py_set_inheritable(fd, inheritable, NULL); + _Py_END_SUPPRESS_IPH + if (result < 0) return NULL; Py_RETURN_NONE; } @@ -16279,7 +16308,9 @@ if (!_PyVerify_fd(fd)) return posix_error(); + _Py_BEGIN_SUPPRESS_IPH blocking = _Py_get_blocking(fd); + _Py_END_SUPPRESS_IPH if (blocking < 0) return NULL; return PyBool_FromLong(blocking); @@ -16295,7 +16326,7 @@ static PyObject* posix_set_blocking(PyObject *self, PyObject *args) { - int fd, blocking; + int fd, blocking, result; if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking)) return NULL; @@ -16303,7 +16334,10 @@ if (!_PyVerify_fd(fd)) return posix_error(); - if (_Py_set_blocking(fd, blocking) < 0) + _Py_BEGIN_SUPPRESS_IPH + result = _Py_set_blocking(fd, blocking); + _Py_END_SUPPRESS_IPH + if (result < 0) return NULL; Py_RETURN_NONE; } diff --git a/PC/msvcrtmodule.c b/PC/msvcrtmodule.c --- a/PC/msvcrtmodule.c +++ b/PC/msvcrtmodule.c @@ -149,7 +149,9 @@ if (!_PyVerify_fd(fd)) return PyErr_SetFromErrno(PyExc_IOError); + _Py_BEGIN_SUPPRESS_IPH handle = _get_osfhandle(fd); + _Py_END_SUPPRESS_IPH if (handle == -1) return PyErr_SetFromErrno(PyExc_IOError); diff --git a/Python/fileutils.c b/Python/fileutils.c --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -5,6 +5,7 @@ #ifdef MS_WINDOWS # include # include +extern int winerror_to_errno(int); #endif #ifdef HAVE_LANGINFO_H @@ -41,9 +42,13 @@ #if defined(MS_WINDOWS) UINT cp; #endif - if (!_PyVerify_fd(fd) || !isatty(fd)) { + int valid; + _Py_BEGIN_SUPPRESS_IPH + valid = _PyVerify_fd(fd) && isatty(fd); + _Py_END_SUPPRESS_IPH + if (!valid) Py_RETURN_NONE; - } + #if defined(MS_WINDOWS) if (fd == 0) cp = GetConsoleCP(); @@ -635,16 +640,15 @@ if (!_PyVerify_fd(fd)) h = INVALID_HANDLE_VALUE; - else + else { + _Py_BEGIN_SUPPRESS_IPH h = (HANDLE)_get_osfhandle(fd); - - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; + _Py_END_SUPPRESS_IPH + } if (h == INVALID_HANDLE_VALUE) { - /* This is really a C library error (invalid file handle). - We set the Win32 error to the closes one matching. */ + /* errno is already set by _get_osfhandle, but we also set + the Win32 error for callers who expect that */ SetLastError(ERROR_INVALID_HANDLE); return -1; } @@ -654,6 +658,7 @@ if (type == FILE_TYPE_UNKNOWN) { DWORD error = GetLastError(); if (error != 0) { + errno = winerror_to_errno(error); return -1; } /* else: valid but unknown file */ @@ -668,6 +673,9 @@ } if (!GetFileInformationByHandle(h, &info)) { + /* The Win32 error is already set, but we also set errno for + callers who expect it */ + errno = winerror_to_errno(GetLastError()); return -1; } @@ -731,7 +739,9 @@ return -1; } + _Py_BEGIN_SUPPRESS_IPH handle = (HANDLE)_get_osfhandle(fd); + _Py_END_SUPPRESS_IPH if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromErrno(PyExc_OSError); @@ -806,7 +816,9 @@ return -1; } + _Py_BEGIN_SUPPRESS_IPH handle = (HANDLE)_get_osfhandle(fd); + _Py_END_SUPPRESS_IPH if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromErrno(PyExc_OSError); @@ -1166,6 +1178,7 @@ } #endif + _Py_BEGIN_SUPPRESS_IPH do { Py_BEGIN_ALLOW_THREADS errno = 0; @@ -1180,6 +1193,7 @@ Py_END_ALLOW_THREADS } while (n < 0 && err == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH if (async_err) { /* read() was interrupted by a signal (failed with EINTR) @@ -1228,6 +1242,7 @@ return -1; } + _Py_BEGIN_SUPPRESS_IPH #ifdef MS_WINDOWS if (count > 32767 && isatty(fd)) { /* Issue #11395: the Windows console returns an error (12: not @@ -1260,6 +1275,7 @@ Py_END_ALLOW_THREADS } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); + _Py_END_SUPPRESS_IPH if (async_err) { /* write() was interrupted by a signal (failed with EINTR) @@ -1411,7 +1427,9 @@ } #ifdef MS_WINDOWS + _Py_BEGIN_SUPPRESS_IPH handle = (HANDLE)_get_osfhandle(fd); + _Py_END_SUPPRESS_IPH if (handle == INVALID_HANDLE_VALUE) { PyErr_SetFromErrno(PyExc_OSError); return -1; @@ -1421,7 +1439,9 @@ ftype = GetFileType(handle); Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH fd = dup(fd); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (fd < 0) { PyErr_SetFromErrno(PyExc_OSError); @@ -1431,13 +1451,17 @@ /* Character files like console cannot be make non-inheritable */ if (ftype != FILE_TYPE_CHAR) { if (_Py_set_inheritable(fd, 0, NULL) < 0) { + _Py_BEGIN_SUPPRESS_IPH close(fd); + _Py_END_SUPPRESS_IPH return -1; } } #elif defined(HAVE_FCNTL_H) && defined(F_DUPFD_CLOEXEC) Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (fd < 0) { PyErr_SetFromErrno(PyExc_OSError); @@ -1446,7 +1470,9 @@ #else Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH fd = dup(fd); + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (fd < 0) { PyErr_SetFromErrno(PyExc_OSError); @@ -1454,7 +1480,9 @@ } if (_Py_set_inheritable(fd, 0, NULL) < 0) { + _Py_BEGIN_SUPPRESS_IPH close(fd); + _Py_END_SUPPRESS_IPH return -1; } #endif @@ -1468,7 +1496,10 @@ int _Py_get_blocking(int fd) { - int flags = fcntl(fd, F_GETFL, 0); + int flags; + _Py_BEGIN_SUPPRESS_IPH + flags = fcntl(fd, F_GETFL, 0); + _Py_END_SUPPRESS_IPH if (flags < 0) { PyErr_SetFromErrno(PyExc_OSError); return -1; @@ -1493,16 +1524,20 @@ #else int flags, res; + _Py_BEGIN_SUPPRESS_IPH flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) - goto error; + if (flags >= 0) { + if (blocking) + flags = flags & (~O_NONBLOCK); + else + flags = flags | O_NONBLOCK; - if (blocking) - flags = flags & (~O_NONBLOCK); - else - flags = flags | O_NONBLOCK; + res = fcntl(fd, F_SETFL, flags); + } else { + res = -1; + } + _Py_END_SUPPRESS_IPH - res = fcntl(fd, F_SETFL, flags); if (res < 0) goto error; #endif @@ -1514,25 +1549,7 @@ } #endif -#ifdef _MSC_VER -#if _MSC_VER >= 1900 - -/* This function lets the Windows CRT validate the file handle without - terminating the process if it's invalid. */ -int -_PyVerify_fd(int fd) -{ - intptr_t osh; - /* Fast check for the only condition we know */ - if (fd < 0) { - _set_errno(EBADF); - return 0; - } - osh = _get_osfhandle(fd); - return osh != (intptr_t)-1; -} - -#elif _MSC_VER >= 1400 +#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 /* Legacy implementation of _PyVerify_fd while transitioning to * MSVC 14.0. This should eventually be removed. (issue23524) */ @@ -1611,5 +1628,4 @@ return 0; } -#endif /* _MSC_VER >= 1900 || _MSC_VER >= 1400 */ -#endif /* defined _MSC_VER */ +#endif /* defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 */ diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1068,11 +1068,12 @@ int dummy_fd; if (fd < 0 || !_PyVerify_fd(fd)) return 0; + _Py_BEGIN_SUPPRESS_IPH dummy_fd = dup(fd); - if (dummy_fd < 0) - return 0; - close(dummy_fd); - return 1; + if (dummy_fd >= 0) + close(dummy_fd); + _Py_END_SUPPRESS_IPH + return dummy_fd >= 0; } /* Initialize sys.stdin, stdout, stderr and builtins.open */ diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -22,12 +22,6 @@ #endif #endif -#if defined _MSC_VER && _MSC_VER >= 1900 -/* Issue #23524: Temporary fix to disable termination due to invalid parameters */ -PyAPI_DATA(void*) _Py_silent_invalid_parameter_handler; -#include -#endif - #ifdef __cplusplus extern "C" { #endif @@ -228,11 +222,6 @@ tstate->next->prev = tstate; interp->tstate_head = tstate; HEAD_UNLOCK(); - -#if defined _MSC_VER && _MSC_VER >= 1900 - /* Issue #23524: Temporary fix to disable termination due to invalid parameters */ - _set_thread_local_invalid_parameter_handler((_invalid_parameter_handler)_Py_silent_invalid_parameter_handler); -#endif } return tstate; diff --git a/Python/traceback.c b/Python/traceback.c --- a/Python/traceback.c +++ b/Python/traceback.c @@ -698,6 +698,7 @@ /* Dump the traceback of each thread */ tstate = PyInterpreterState_ThreadHead(interp); nthreads = 0; + _Py_BEGIN_SUPPRESS_IPH do { if (nthreads != 0) @@ -711,6 +712,7 @@ tstate = PyThreadState_Next(tstate); nthreads++; } while (tstate != NULL); + _Py_END_SUPPRESS_IPH return NULL; }