diff -urNp old/include/net-snmp/library/large_fd_set.h new/include/net-snmp/library/large_fd_set.h --- old/include/net-snmp/library/large_fd_set.h 2012-10-10 00:28:58.000000000 +0200 +++ new/include/net-snmp/library/large_fd_set.h 2017-04-04 14:36:27.307180033 +0200 @@ -55,8 +55,9 @@ extern "C" { * Number of bytes needed to store a number of file descriptors as a * struct fd_set. */ -#define NETSNMP_FD_SET_BYTES(setsize) \ - (sizeof(fd_set) + ((setsize) - FD_SETSIZE) * sizeof(SOCKET)) +#define NETSNMP_FD_SET_BYTES(setsize) \ + (sizeof(fd_set) + ((setsize) > FD_SETSIZE ? \ + ((setsize) - FD_SETSIZE) * sizeof(SOCKET) : 0)) /** Remove all sockets from the set *fdset. */ #define NETSNMP_LARGE_FD_ZERO(fdset) \ @@ -91,9 +92,10 @@ int netsnmp_large_fd_is_set(SOCKET fd * Number of bytes needed to store a number of file descriptors as a * struct fd_set. */ -#define NETSNMP_FD_SET_BYTES(setsize) \ - (sizeof(fd_set) + NETSNMP_FD_SET_ELEM_COUNT((setsize) - FD_SETSIZE) \ - * NETSNMP_FD_MASK_SIZE) +#define NETSNMP_FD_SET_BYTES(setsize) \ + (sizeof(fd_set) + ((setsize) > FD_SETSIZE ? \ + NETSNMP_FD_SET_ELEM_COUNT((setsize) - FD_SETSIZE) \ + * NETSNMP_FD_MASK_SIZE : 0)) /** Remove all file descriptors from the set *fdset. */ #define NETSNMP_LARGE_FD_ZERO(fdset) \ diff -urNp old/snmplib/large_fd_set.c new/snmplib/large_fd_set.c --- old/snmplib/large_fd_set.c 2012-10-10 00:28:58.000000000 +0200 +++ new/snmplib/large_fd_set.c 2017-04-04 15:03:20.580810774 +0200 @@ -21,6 +21,10 @@ #if !defined(cygwin) && defined(HAVE_WINSOCK_H) +#define LFD_SET(n, p) FD_SET(n, p) +#define LFD_CLR(n, p) FD_CLR(n, p) +#define LFD_ISSET(n, p) FD_ISSET(n, p) + void netsnmp_large_fd_setfd(SOCKET fd, netsnmp_large_fd_set * fdset) { @@ -28,18 +32,18 @@ netsnmp_large_fd_setfd(SOCKET fd, netsnm netsnmp_assert(fd != INVALID_SOCKET); - if (fdset->lfs_set.fd_count == fdset->lfs_setsize) + if (fdset->lfs_setptr->fd_count == fdset->lfs_setsize) netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1)); - for (i = 0; i < fdset->lfs_set.fd_count; i++) { - if (fdset->lfs_set.fd_array[i] == (SOCKET) (fd)) + for (i = 0; i < fdset->lfs_setptr->fd_count; i++) { + if (fdset->lfs_setptr->fd_array[i] == fd) break; } - if (i == fdset->lfs_set.fd_count - && fdset->lfs_set.fd_count < fdset->lfs_setsize) { - fdset->lfs_set.fd_count++; - fdset->lfs_set.fd_array[i] = fd; + if (i == fdset->lfs_setptr->fd_count && + fdset->lfs_setptr->fd_count < fdset->lfs_setsize) { + fdset->lfs_setptr->fd_count++; + fdset->lfs_setptr->fd_array[i] = fd; } } @@ -50,14 +54,14 @@ netsnmp_large_fd_clr(SOCKET fd, netsnmp_ netsnmp_assert(fd != INVALID_SOCKET); - for (i = 0; i < fdset->lfs_set.fd_count; i++) { - if (fdset->lfs_set.fd_array[i] == fd) { - while (i < fdset->lfs_set.fd_count - 1) { - fdset->lfs_set.fd_array[i] = - fdset->lfs_set.fd_array[i + 1]; + for (i = 0; i < fdset->lfs_setptr->fd_count; i++) { + if (fdset->lfs_setptr->fd_array[i] == fd) { + while (i < fdset->lfs_setptr->fd_count - 1) { + fdset->lfs_setptr->fd_array[i] = + fdset->lfs_setptr->fd_array[i + 1]; i++; } - fdset->lfs_set.fd_count--; + fdset->lfs_setptr->fd_count--; break; } } @@ -70,8 +74,8 @@ netsnmp_large_fd_is_set(SOCKET fd, netsn netsnmp_assert(fd != INVALID_SOCKET); - for (i = 0; i < fdset->lfs_set.fd_count; i++) { - if (fdset->lfs_set.fd_array[i] == fd) + for (i = 0; i < fdset->lfs_setptr->fd_count; i++) { + if (fdset->lfs_setptr->fd_array[i] == fd) return 1; } return 0; @@ -79,6 +83,43 @@ netsnmp_large_fd_is_set(SOCKET fd, netsn #else + /* + * Recent versions of glibc trigger abort() if FD_SET(), FD_CLR() or + * FD_ISSET() is invoked with n >= FD_SETSIZE. Hence these replacement + * functions. However, since NFDBITS != 8 * sizeof(fd_set.fds_bits[0]) for at + * least HP-UX on ia64 and since that combination uses big endian, use the + * macros from on such systems. + */ +NETSNMP_STATIC_INLINE void LFD_SET(unsigned n, fd_set *p) +{ + enum { nfdbits = 8 * sizeof(p->fds_bits[0]) }; + + if (nfdbits == NFDBITS) + p->fds_bits[n / nfdbits] |= (1ULL << (n % nfdbits)); + else + FD_SET(n, p); +} + +NETSNMP_STATIC_INLINE void LFD_CLR(unsigned n, fd_set *p) +{ + enum { nfdbits = 8 * sizeof(p->fds_bits[0]) }; + + if (nfdbits == NFDBITS) + p->fds_bits[n / nfdbits] &= ~(1ULL << (n % nfdbits)); + else + FD_CLR(n, p); +} + +NETSNMP_STATIC_INLINE unsigned LFD_ISSET(unsigned n, const fd_set *p) +{ + enum { nfdbits = 8 * sizeof(p->fds_bits[0]) }; + + if (nfdbits == NFDBITS) + return (p->fds_bits[n / nfdbits] & (1ULL << (n % nfdbits))) != 0; + else + return FD_ISSET(n, p) != 0; +} + void netsnmp_large_fd_setfd(int fd, netsnmp_large_fd_set * fdset) { @@ -87,7 +128,7 @@ netsnmp_large_fd_setfd(int fd, netsnmp_l while (fd >= (int)fdset->lfs_setsize) netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1)); - FD_SET(fd, fdset->lfs_setptr); + LFD_SET(fd, fdset->lfs_setptr); } void @@ -96,7 +137,7 @@ netsnmp_large_fd_clr(int fd, netsnmp_lar netsnmp_assert(fd >= 0); if ((unsigned)fd < fdset->lfs_setsize) - FD_CLR(fd, fdset->lfs_setptr); + LFD_CLR(fd, fdset->lfs_setptr); } int @@ -104,7 +145,7 @@ netsnmp_large_fd_is_set(int fd, netsnmp_ { netsnmp_assert(fd >= 0); - return (unsigned)fd < fdset->lfs_setsize && FD_ISSET(fd, fdset->lfs_setptr); + return ((unsigned)fd < fdset->lfs_setsize && LFD_ISSET(fd, fdset->lfs_setptr)); } #endif @@ -174,22 +215,24 @@ netsnmp_large_fd_set_resize(netsnmp_larg } #if defined(cygwin) || !defined(HAVE_WINSOCK_H) - { + /* + * Unix: when enlarging, clear the file descriptors defined in the + * resized *fdset but that were not defined in the original *fdset. + */ + if ( fdset->lfs_setsize == 0 && setsize == FD_SETSIZE ) { + /* In this case we can use the OS's FD_ZERO */ + FD_ZERO(fdset->lfs_setptr); + } else { int i; - - /* - * Unix: when enlarging, clear the file descriptors defined in the - * resized *fdset but that were not defined in the original *fdset. - */ for (i = fdset->lfs_setsize; i < setsize; i++) - FD_CLR(i, fdset->lfs_setptr); + LFD_CLR(i, fdset->lfs_setptr); } #endif fdset->lfs_setsize = setsize; #if !defined(cygwin) && defined(HAVE_WINSOCK_H) - if (setsize < fdset->lfs_set.fd_count) - fdset->lfs_set.fd_count = setsize; + if (setsize < fdset->lfs_setptr->fd_count) + fdset->lfs_setptr->fd_count = setsize; #endif success: return 1; @@ -197,7 +240,7 @@ success: out_of_mem: fdset->lfs_setsize = 0; #if !defined(cygwin) && defined(HAVE_WINSOCK_H) - fdset->lfs_set.fd_count = 0; + fdset->lfs_setptr->fd_count = 0; #endif return 0; }