diff --git a/src/library/parallel/src/fork.c b/src/library/parallel/src/fork.c index 5f3d29cdec1..f4aef9258a7 100644 --- a/src/library/parallel/src/fork.c +++ b/src/library/parallel/src/fork.c @@ -1,7 +1,7 @@ /* * R : A Computer Language for Statistical Data Analysis * (C) Copyright 2008-2011 Simon Urbanek - * Copyright 2011-2022 R Core Team. + * Copyright 2011-2023 R Core Team. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -816,6 +816,8 @@ SEXP mc_send_child_stdin(SEXP sPid, SEXP what) void fdcopy(fd_set *dst, fd_set *src, int nfds) { FD_ZERO(dst); + if (nfds > FD_SETSIZE) + error("file descriptor is too large for select()"); for(int i = 0; i < nfds; i++) if (FD_ISSET(i, src)) FD_SET(i, dst); } @@ -847,7 +849,7 @@ SEXP mc_select_children(SEXP sTimeout, SEXP sWhich) unsigned int k = 0; while (k < wlen) { if (which[k++] == ci->pid) { - if (ci->pfd > FD_SETSIZE) + if (ci->pfd >= FD_SETSIZE) error("file descriptor is too large for select()"); FD_SET(ci->pfd, &fs); if (ci->pfd > maxfd) maxfd = ci->pfd; @@ -860,7 +862,7 @@ SEXP mc_select_children(SEXP sTimeout, SEXP sWhich) } } else { /* not sure if this should be allowed */ - if (ci->pfd > FD_SETSIZE) + if (ci->pfd >= FD_SETSIZE) error("file descriptor is too large for select()"); FD_SET(ci->pfd, &fs); if (ci->pfd > maxfd) maxfd = ci->pfd; @@ -1061,7 +1063,11 @@ SEXP mc_read_children(SEXP sTimeout) while (ci) { if (!ci->detached && ci->ppid == ppid) { if (ci->pfd > maxfd) maxfd = ci->pfd; - if (ci->pfd >= 0) FD_SET(ci->pfd, &fs); + if (ci->pfd >= 0) { + if (ci->pfd >= FD_SETSIZE) + error("file descriptor is too large for select()"); + FD_SET(ci->pfd, &fs); + } } ci = ci -> next; } diff --git a/src/unix/sys-std.c b/src/unix/sys-std.c index c0f98f14c3a..3d355238e76 100644 --- a/src/unix/sys-std.c +++ b/src/unix/sys-std.c @@ -120,7 +120,7 @@ int R_SelectEx(int n, fd_set *readfds, fd_set *writefds, platforms. If this still turns out to be limiting we will probably need to rewrite internals to use poll() instead of select(). LT */ - if (n > FD_SETSIZE) + if (n >= FD_SETSIZE) error("file descriptor is too large for select()"); if (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0) @@ -229,6 +229,8 @@ addInputHandler(InputHandler *handlers, int fd, InputHandlerProc handler, input = R_Calloc(1, InputHandler); input->activity = activity; + if (fd >= FD_SETSIZE) + error("file descriptor is too large for select()"); input->fileDescriptor = fd; input->handler = handler; @@ -382,8 +384,11 @@ setSelectMask(InputHandler *handlers, fd_set *readMask) FD_ZERO(readMask); /* If we are dealing with BasicInputHandler always put stdin */ - if(handlers == &BasicInputHandler) + if(handlers == &BasicInputHandler) { handlers->fileDescriptor = fileno(stdin); + if (handlers->fileDescriptor >= FD_SETSIZE) + error("file descriptor is too large for select()"); + } while(tmp) { FD_SET(tmp->fileDescriptor, readMask);