Mercurial > cpython-lru_cache-weakref
diff Modules/socketmodule.c @ 36453:af67b6265af6 2.4
Backport:
Bug #876637, prevent stack corruption when socket descriptor
is larger than FD_SETSIZE.
This can only be acheived with ulimit -n SOME_NUMBER_BIGGER_THAN_FD_SETSIZE
which is typically only available to root. Since this wouldn't normally
be run in a test (ie, run as root), it doesn't seem too worthwhile to
add a normal test. The bug report has one version of a test. I've
written another. Not sure what the best thing to do is.
Do the check before calling internal_select() because we can't set
an error in between Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
This seemed the clearest solution.
| author | Neal Norwitz <nnorwitz@gmail.com> |
|---|---|
| date | Tue, 07 Feb 2006 07:17:37 +0000 |
| parents | 57f630a9de26 |
| children | 65ae730b6231 |
line wrap: on
line diff
--- a/Modules/socketmodule.c Sun Feb 05 06:00:54 2006 +0000 +++ b/Modules/socketmodule.c Tue Feb 07 07:17:37 2006 +0000 @@ -390,6 +390,16 @@ there has to be a circular reference. */ static PyTypeObject sock_type; +/* Can we call select() with this socket without a buffer overrun? */ +#define IS_SELECTABLE(s) ((s)->sock_fd < FD_SETSIZE) + +static PyObject* +select_error(void) +{ + PyErr_SetString(socket_error, "unable to select on socket"); + return NULL; +} + /* Convenience function to raise an error according to errno and return a NULL pointer from a function. */ @@ -1362,6 +1372,9 @@ newfd = -1; #endif + if (!IS_SELECTABLE(s)) + return select_error(); + Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 0); if (!timeout) @@ -1690,7 +1703,8 @@ #ifdef MS_WINDOWS if (s->sock_timeout > 0.0) { - if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK) { + if (res < 0 && WSAGetLastError() == WSAEWOULDBLOCK && + IS_SELECTABLE(s)) { /* This is a mess. Best solution: trust select */ fd_set fds; fd_set fds_exc; @@ -1735,7 +1749,7 @@ #else if (s->sock_timeout > 0.0) { - if (res < 0 && errno == EINPROGRESS) { + if (res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) { timeout = internal_select(s, 1); res = connect(s->sock_fd, addr, addrlen); if (res < 0 && errno == EISCONN) @@ -2038,6 +2052,9 @@ if (buf == NULL) return NULL; + if (!IS_SELECTABLE(s)) + return select_error(); + #ifndef __VMS Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 0); @@ -2131,6 +2148,9 @@ if (buf == NULL) return NULL; + if (!IS_SELECTABLE(s)) + return select_error(); + Py_BEGIN_ALLOW_THREADS memset(&addrbuf, 0, addrlen); timeout = internal_select(s, 0); @@ -2192,6 +2212,9 @@ if (!PyArg_ParseTuple(args, "s#|i:send", &buf, &len, &flags)) return NULL; + if (!IS_SELECTABLE(s)) + return select_error(); + #ifndef __VMS Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 1); @@ -2257,6 +2280,9 @@ if (!PyArg_ParseTuple(args, "s#|i:sendall", &buf, &len, &flags)) return NULL; + if (!IS_SELECTABLE(s)) + return select_error(); + Py_BEGIN_ALLOW_THREADS do { timeout = internal_select(s, 1); @@ -2311,6 +2337,9 @@ if (!getsockaddrarg(s, addro, &addr, &addrlen)) return NULL; + if (!IS_SELECTABLE(s)) + return select_error(); + Py_BEGIN_ALLOW_THREADS timeout = internal_select(s, 1); if (!timeout)
