From aa26b275034c07784c4d64e9a2bc26c742577327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Sun, 28 Aug 2011 17:51:43 +0200 Subject: Issue #12287: Fix a stack corruption in ossaudiodev module when the FD is greater than FD_SETSIZE. --- Include/fileobject.h | 7 +++++++ Misc/NEWS | 3 +++ Modules/_ssl.c | 4 +--- Modules/ossaudiodev.c | 5 +++++ Modules/selectmodule.c | 9 +-------- Modules/socketmodule.c | 12 ++++-------- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Include/fileobject.h b/Include/fileobject.h index c4a2a2b..a99c94d 100644 --- a/Include/fileobject.h +++ b/Include/fileobject.h @@ -44,6 +44,13 @@ int _PyVerify_fd(int fd); #endif #endif /* Py_LIMITED_API */ +/* A routine to check if a file descriptor can be select()-ed. */ +#ifdef HAVE_SELECT + #define _PyIsSelectable_fd(FD) (((FD) >= 0) && ((FD) < FD_SETSIZE)) +#else + #define _PyIsSelectable_fd(FD) (1) +#endif /* HAVE_SELECT */ + #ifdef __cplusplus } #endif diff --git a/Misc/NEWS b/Misc/NEWS index 23b336b..4d285a3 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Core and Builtins Library ------- +- Issue #12287: Fix a stack corruption in ossaudiodev module when the FD is + greater than FD_SETSIZE. + - Issue #12839: Fix crash in zlib module due to version mismatch. Fix by Richard M. Tew. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 27dcdbc..b27353a 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1023,10 +1023,8 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) #endif /* Guard against socket too large for select*/ -#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE - if (s->sock_fd >= FD_SETSIZE) + if (!_PyIsSelectable_fd(s->sock_fd)) return SOCKET_TOO_LARGE_FOR_SELECT; -#endif /* Construct the arguments to select */ tv.tv_sec = (int)s->sock_timeout; diff --git a/Modules/ossaudiodev.c b/Modules/ossaudiodev.c index e660e50..cdf6beb 100644 --- a/Modules/ossaudiodev.c +++ b/Modules/ossaudiodev.c @@ -425,6 +425,11 @@ oss_writeall(oss_audio_t *self, PyObject *args) if (!PyArg_ParseTuple(args, "y#:write", &cp, &size)) return NULL; + if (!_PyIsSelectable_fd(self->fd)) { + PyErr_SetString(PyExc_ValueError, + "file descriptor out of range for select"); + return NULL; + } /* use select to wait for audio device to be available */ FD_ZERO(&write_set_fds); FD_SET(self->fd, &write_set_fds); diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 1285e65..2452a65 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -110,7 +110,7 @@ seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) #if defined(_MSC_VER) max = 0; /* not used for Win32 */ #else /* !_MSC_VER */ - if (v < 0 || v >= FD_SETSIZE) { + if (!_PyIsSelectable_fd(v)) { PyErr_SetString(PyExc_ValueError, "filedescriptor out of range in select()"); goto finally; @@ -160,13 +160,6 @@ set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) for (j = 0; fd2obj[j].sentinel >= 0; j++) { fd = fd2obj[j].fd; if (FD_ISSET(fd, set)) { -#ifndef _MSC_VER - if (fd > FD_SETSIZE) { - PyErr_SetString(PyExc_SystemError, - "filedescriptor out of range returned in select()"); - goto finally; - } -#endif o = fd2obj[j].obj; fd2obj[j].obj = NULL; /* transfer ownership */ diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index fcdbf8a..d3e5c75 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -455,18 +455,14 @@ static PyTypeObject sock_type; #include #endif -#ifdef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE -/* Platform can select file descriptors beyond FD_SETSIZE */ -#define IS_SELECTABLE(s) 1 -#elif defined(HAVE_POLL) +#ifdef HAVE_POLL /* Instead of select(), we'll use poll() since poll() works on any fd. */ #define IS_SELECTABLE(s) 1 /* Can we call select() with this socket without a buffer overrun? */ #else -/* POSIX says selecting file descriptors beyond FD_SETSIZE - has undefined behaviour. If there's no timeout left, we don't have to - call select, so it's a safe, little white lie. */ -#define IS_SELECTABLE(s) ((s)->sock_fd < FD_SETSIZE || s->sock_timeout <= 0.0) +/* If there's no timeout left, we don't have to call select, so it's a safe, + * little white lie. */ +#define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0.0) #endif static PyObject* -- cgit v0.12