[Python-checkins] cpython: Issue #23524: Replace _PyVerify_fd function with calls to
steve.dower
python-checkins at python.org
Sun Apr 12 06:32:32 CEST 2015
https://hg.python.org/cpython/rev/32652360d1c3
changeset: 95552:32652360d1c3
user: Steve Dower <steve.dower at microsoft.com>
date: Sun Apr 12 00:26:27 2015 -0400
summary:
Issue #23524: Replace _PyVerify_fd function with calls to _set_thread_local_invalid_parameter_handler.
files:
Include/fileutils.h | 2 +-
Include/pyport.h | 20 ++++
Modules/_io/fileio.c | 14 +++-
Modules/mmapmodule.c | 4 +-
Modules/posixmodule.c | 56 ++++++++++--
PC/invalid_parameter_handler.c | 4 +-
PC/msvcrtmodule.c | 2 +
Python/fileutils.c | 95 ++++++++++++---------
Python/pylifecycle.c | 9 +-
Python/pystate.c | 11 --
Python/traceback.c | 2 +
11 files changed, 150 insertions(+), 69 deletions(-)
diff --git a/Include/fileutils.h b/Include/fileutils.h
--- a/Include/fileutils.h
+++ b/Include/fileutils.h
@@ -121,7 +121,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/pyport.h b/Include/pyport.h
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -877,4 +877,24 @@
#define PY_LITTLE_ENDIAN 1
#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
+
+extern _invalid_parameter_handler _Py_silent_invalid_parameter_handler;
+#define _Py_BEGIN_SUPPRESS_IPH { _invalid_parameter_handler _Py_old_handler = \
+ _set_thread_local_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_PYPORT_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;
@@ -599,11 +601,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_noraise(self->fd, &status) == 0)
end = status.st_size;
else
@@ -792,11 +797,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;
@@ -951,7 +958,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
@@ -1325,11 +1325,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)
@@ -4359,6 +4360,7 @@
int result;
Py_BEGIN_ALLOW_THREADS
+ _Py_BEGIN_SUPPRESS_IPH
#ifdef MS_WINDOWS
if (path->wide)
result = Py_DeleteFileW(path->wide);
@@ -4373,6 +4375,7 @@
#endif /* HAVE_UNLINKAT */
result = unlink(path->narrow);
#endif
+ _Py_END_SUPPRESS_IPH
Py_END_ALLOW_THREADS
if (result)
@@ -7692,6 +7695,7 @@
flags |= O_CLOEXEC;
#endif
+ _Py_BEGIN_SUPPRESS_IPH
do {
Py_BEGIN_ALLOW_THREADS
#ifdef MS_WINDOWS
@@ -7707,6 +7711,7 @@
fd = open(path->narrow, flags, mode);
Py_END_ALLOW_THREADS
} while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ _Py_END_SUPPRESS_IPH
if (fd == -1) {
if (!async_err)
@@ -7745,7 +7750,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();
@@ -7769,9 +7776,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;
}
@@ -7823,7 +7832,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();
@@ -7957,11 +7968,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();
@@ -8168,7 +8181,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()));
@@ -8276,6 +8291,7 @@
}
}
+ _Py_BEGIN_SUPPRESS_IPH
do {
Py_BEGIN_ALLOW_THREADS
#ifdef __APPLE__
@@ -8285,6 +8301,7 @@
#endif
Py_END_ALLOW_THREADS
} while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
+ _Py_END_SUPPRESS_IPH
if (sf.headers != NULL)
iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
@@ -8401,9 +8418,13 @@
os_isatty_impl(PyModuleDef *module, int fd)
/*[clinic end generated code: output=acec9d3c29d16d33 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;
}
@@ -8598,7 +8619,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()));
@@ -11193,12 +11216,16 @@
os_get_inheritable_impl(PyModuleDef *module, int fd)
/*[clinic end generated code: output=36110bb36efaa21e 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;
}
@@ -11215,10 +11242,14 @@
os_set_inheritable_impl(PyModuleDef *module, int fd, int inheritable)
/*[clinic end generated code: output=2ac5c6ce8623f045 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;
}
@@ -11289,7 +11320,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);
@@ -11305,7 +11338,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;
@@ -11313,7 +11346,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/invalid_parameter_handler.c b/PC/invalid_parameter_handler.c
--- a/PC/invalid_parameter_handler.c
+++ b/PC/invalid_parameter_handler.c
@@ -15,8 +15,8 @@
unsigned int line,
uintptr_t pReserved) { }
-void *_Py_silent_invalid_parameter_handler =
- (void*)_silent_invalid_parameter_handler;
+_invalid_parameter_handler _Py_silent_invalid_parameter_handler = _silent_invalid_parameter_handler;
+
#endif
#endif
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 <malloc.h>
# include <windows.h>
+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();
@@ -610,16 +615,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;
}
@@ -628,8 +632,10 @@
type = GetFileType(h);
if (type == FILE_TYPE_UNKNOWN) {
DWORD error = GetLastError();
- if (error != 0)
+ if (error != 0) {
+ errno = winerror_to_errno(error);
return -1;
+ }
/* else: valid but unknown file */
}
@@ -642,6 +648,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;
}
@@ -735,7 +744,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);
@@ -810,7 +821,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);
@@ -1171,6 +1184,7 @@
}
#endif
+ _Py_BEGIN_SUPPRESS_IPH
do {
Py_BEGIN_ALLOW_THREADS
errno = 0;
@@ -1185,6 +1199,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)
@@ -1219,6 +1234,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
@@ -1264,6 +1280,7 @@
err = errno;
} while (n < 0 && err == EINTR);
}
+ _Py_END_SUPPRESS_IPH
if (async_err) {
/* write() was interrupted by a signal (failed with EINTR)
@@ -1451,7 +1468,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;
@@ -1461,7 +1480,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);
@@ -1471,13 +1492,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);
@@ -1486,7 +1511,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);
@@ -1494,7 +1521,9 @@
}
if (_Py_set_inheritable(fd, 0, NULL) < 0) {
+ _Py_BEGIN_SUPPRESS_IPH
close(fd);
+ _Py_END_SUPPRESS_IPH
return -1;
}
#endif
@@ -1508,7 +1537,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;
@@ -1533,16 +1565,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
@@ -1554,25 +1590,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)
*/
@@ -1651,5 +1669,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 <stdlib.h>
-#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
@@ -717,6 +717,7 @@
/* Dump the traceback of each thread */
tstate = PyInterpreterState_ThreadHead(interp);
nthreads = 0;
+ _Py_BEGIN_SUPPRESS_IPH
do
{
if (nthreads != 0)
@@ -730,6 +731,7 @@
tstate = PyThreadState_Next(tstate);
nthreads++;
} while (tstate != NULL);
+ _Py_END_SUPPRESS_IPH
return NULL;
}
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list