summaryrefslogtreecommitdiff
path: root/lib/select.c
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2012-10-02 15:29:13 -0600
committerEric Blake <eblake@redhat.com>2012-10-02 19:39:20 -0600
commit9500a55f083bb8e55ee938e4532ae6baea702e6b (patch)
tree763986d43ad9152c39da431080287959e3c8d5e9 /lib/select.c
parent2f58d08d66740bfe7fe5c581027965da04afecd7 (diff)
downloadgnulib-9500a55f083bb8e55ee938e4532ae6baea702e6b.tar.gz
select: reject invalid file descriptors
POSIX requires invalid file descriptors to be detected rather than silently ignored. FreeBSD 8.2 detects if fd 0 has been closed and appears in a set while fd 1 is still open, but mistakenly optimizes and refuses to check any fds in the set beyond the maximum open fd. * m4/select.m4 (gl_FUNC_SELECT): Probe for FreeBSD bug. * lib/select.c (rpl_select) [!win32]: Work around it. * modules/select (Depends-on): Add dup2. * doc/posix-functions/select.texi (select): Document this.
Diffstat (limited to 'lib/select.c')
-rw-r--r--lib/select.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/lib/select.c b/lib/select.c
index 4db09a353d..1ff6652c65 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -507,6 +507,8 @@ restart:
#include <sys/select.h>
#include <stddef.h> /* NULL */
+#include <errno.h>
+#include <unistd.h>
#undef select
@@ -514,6 +516,23 @@ int
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
struct timeval *timeout)
{
+ int i;
+
+ /* FreeBSD 8.2 has a bug: it does not always detect invalid fds. */
+ if (nfds < 0 || nfds > FD_SETSIZE)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ for (i = 0; i < nfds; i++)
+ {
+ if (((rfds && FD_ISSET (i, rfds))
+ || (wfds && FD_ISSET (i, wfds))
+ || (xfds && FD_ISSET (i, xfds)))
+ && dup2 (i, i) != i)
+ return -1;
+ }
+
/* Interix 3.5 has a bug: it does not support nfds == 0. */
if (nfds == 0)
{