diff options
author | Eric Blake <eblake@redhat.com> | 2012-10-02 15:29:13 -0600 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2012-10-02 19:39:20 -0600 |
commit | 9500a55f083bb8e55ee938e4532ae6baea702e6b (patch) | |
tree | 763986d43ad9152c39da431080287959e3c8d5e9 /lib/select.c | |
parent | 2f58d08d66740bfe7fe5c581027965da04afecd7 (diff) | |
download | gnulib-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.c | 19 |
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) { |