Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aa26b27

Browse files
author
Charles-François Natali
committed
Issue #12287: Fix a stack corruption in ossaudiodev module when the FD is
greater than FD_SETSIZE.
1 parent 524148a commit aa26b27

6 files changed

Lines changed: 21 additions & 19 deletions

File tree

Include/fileobject.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ int _PyVerify_fd(int fd);
4444
#endif
4545
#endif /* Py_LIMITED_API */
4646

47+
/* A routine to check if a file descriptor can be select()-ed. */
48+
#ifdef HAVE_SELECT
49+
#define _PyIsSelectable_fd(FD) (((FD) >= 0) && ((FD) < FD_SETSIZE))
50+
#else
51+
#define _PyIsSelectable_fd(FD) (1)
52+
#endif /* HAVE_SELECT */
53+
4754
#ifdef __cplusplus
4855
}
4956
#endif

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Core and Builtins
2222
Library
2323
-------
2424

25+
- Issue #12287: Fix a stack corruption in ossaudiodev module when the FD is
26+
greater than FD_SETSIZE.
27+
2528
- Issue #12839: Fix crash in zlib module due to version mismatch.
2629
Fix by Richard M. Tew.
2730

Modules/_ssl.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,10 +1023,8 @@ check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing)
10231023
#endif
10241024

10251025
/* Guard against socket too large for select*/
1026-
#ifndef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
1027-
if (s->sock_fd >= FD_SETSIZE)
1026+
if (!_PyIsSelectable_fd(s->sock_fd))
10281027
return SOCKET_TOO_LARGE_FOR_SELECT;
1029-
#endif
10301028

10311029
/* Construct the arguments to select */
10321030
tv.tv_sec = (int)s->sock_timeout;

Modules/ossaudiodev.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,11 @@ oss_writeall(oss_audio_t *self, PyObject *args)
425425
if (!PyArg_ParseTuple(args, "y#:write", &cp, &size))
426426
return NULL;
427427

428+
if (!_PyIsSelectable_fd(self->fd)) {
429+
PyErr_SetString(PyExc_ValueError,
430+
"file descriptor out of range for select");
431+
return NULL;
432+
}
428433
/* use select to wait for audio device to be available */
429434
FD_ZERO(&write_set_fds);
430435
FD_SET(self->fd, &write_set_fds);

Modules/selectmodule.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
110110
#if defined(_MSC_VER)
111111
max = 0; /* not used for Win32 */
112112
#else /* !_MSC_VER */
113-
if (v < 0 || v >= FD_SETSIZE) {
113+
if (!_PyIsSelectable_fd(v)) {
114114
PyErr_SetString(PyExc_ValueError,
115115
"filedescriptor out of range in select()");
116116
goto finally;
@@ -160,13 +160,6 @@ set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
160160
for (j = 0; fd2obj[j].sentinel >= 0; j++) {
161161
fd = fd2obj[j].fd;
162162
if (FD_ISSET(fd, set)) {
163-
#ifndef _MSC_VER
164-
if (fd > FD_SETSIZE) {
165-
PyErr_SetString(PyExc_SystemError,
166-
"filedescriptor out of range returned in select()");
167-
goto finally;
168-
}
169-
#endif
170163
o = fd2obj[j].obj;
171164
fd2obj[j].obj = NULL;
172165
/* transfer ownership */

Modules/socketmodule.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -455,18 +455,14 @@ static PyTypeObject sock_type;
455455
#include <sys/poll.h>
456456
#endif
457457

458-
#ifdef Py_SOCKET_FD_CAN_BE_GE_FD_SETSIZE
459-
/* Platform can select file descriptors beyond FD_SETSIZE */
460-
#define IS_SELECTABLE(s) 1
461-
#elif defined(HAVE_POLL)
458+
#ifdef HAVE_POLL
462459
/* Instead of select(), we'll use poll() since poll() works on any fd. */
463460
#define IS_SELECTABLE(s) 1
464461
/* Can we call select() with this socket without a buffer overrun? */
465462
#else
466-
/* POSIX says selecting file descriptors beyond FD_SETSIZE
467-
has undefined behaviour. If there's no timeout left, we don't have to
468-
call select, so it's a safe, little white lie. */
469-
#define IS_SELECTABLE(s) ((s)->sock_fd < FD_SETSIZE || s->sock_timeout <= 0.0)
463+
/* If there's no timeout left, we don't have to call select, so it's a safe,
464+
* little white lie. */
465+
#define IS_SELECTABLE(s) (_PyIsSelectable_fd((s)->sock_fd) || (s)->sock_timeout <= 0.0)
470466
#endif
471467

472468
static PyObject*

0 commit comments

Comments
 (0)