libc: allocate file descriptor sets on the stack

The 'fd_set' size calculation in the current version of the 'poll()'
function results in an  amount which is smaller than the size of the
'fd_set' data type. With this patch the file descriptor sets get
allocated as plain stack variables.

Fixes #335.
This commit is contained in:
Christian Prochaska 2012-08-22 16:13:59 +02:00 committed by Norman Feske
parent 59a9d1f2b0
commit 7f092be94c

View File

@ -51,8 +51,7 @@ poll(struct pollfd fds[], nfds_t nfds, int timeout)
{ {
nfds_t i; nfds_t i;
int saved_errno, ret, fd, maxfd = 0; int saved_errno, ret, fd, maxfd = 0;
fd_set *readfds = NULL, *writefds = NULL, *exceptfds = NULL; fd_set readfds, writefds, exceptfds;
size_t nmemb;
struct timeval tv, *tvp = NULL; struct timeval tv, *tvp = NULL;
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
@ -64,27 +63,18 @@ poll(struct pollfd fds[], nfds_t nfds, int timeout)
maxfd = MAX(maxfd, fd); maxfd = MAX(maxfd, fd);
} }
nmemb = howmany(maxfd + 1 , NFDBITS);
if ((readfds = (fd_set *) calloc(nmemb, sizeof(fd_mask))) == NULL ||
(writefds = (fd_set *) calloc(nmemb, sizeof(fd_mask))) == NULL ||
(exceptfds = (fd_set *) calloc(nmemb, sizeof(fd_mask))) == NULL) {
/*saved_errno = ENOMEM;*/
ret = -1;
goto out;
}
/* populate event bit vectors for the events we're interested in */ /* populate event bit vectors for the events we're interested in */
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
fd = fds[i].fd; fd = fds[i].fd;
if (fd == -1) if (fd == -1)
continue; continue;
if (fds[i].events & POLLIN) { if (fds[i].events & POLLIN) {
FD_SET(fd, readfds); FD_SET(fd, &readfds);
FD_SET(fd, exceptfds); FD_SET(fd, &exceptfds);
} }
if (fds[i].events & POLLOUT) { if (fds[i].events & POLLOUT) {
FD_SET(fd, writefds); FD_SET(fd, &writefds);
FD_SET(fd, exceptfds); FD_SET(fd, &exceptfds);
} }
} }
@ -94,34 +84,25 @@ poll(struct pollfd fds[], nfds_t nfds, int timeout)
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
tvp = &tv; tvp = &tv;
} }
ret = select(maxfd + 1, &readfds, &writefds, &exceptfds, tvp);
ret = select(maxfd + 1, readfds, writefds, exceptfds, tvp);
/*saved_errno = errno;*/ /*saved_errno = errno;*/
/* scan through select results and set poll() flags */ /* scan through select results and set poll() flags */
for (i = 0; i < nfds; i++) { for (i = 0; i < nfds; i++) {
fd = fds[i].fd; fd = fds[i].fd;
fds[i].revents = 0; fds[i].revents = 0;
if (fd == -1) if (fd == -1)
continue; continue;
if (FD_ISSET(fd, readfds)) { if (FD_ISSET(fd, &readfds)) {
fds[i].revents |= POLLIN; fds[i].revents |= POLLIN;
} }
if (FD_ISSET(fd, writefds)) { if (FD_ISSET(fd, &writefds)) {
fds[i].revents |= POLLOUT; fds[i].revents |= POLLOUT;
} }
if (FD_ISSET(fd, exceptfds)) { if (FD_ISSET(fd, &exceptfds)) {
fds[i].revents |= POLLERR; fds[i].revents |= POLLERR;
} }
} }
out:
if (readfds != NULL)
free(readfds);
if (writefds != NULL)
free(writefds);
if (exceptfds != NULL)
free(exceptfds);
/* /*
if (ret == -1) if (ret == -1)
errno = saved_errno; errno = saved_errno;