This fixes stack smashing I've seen in Okteta. The problem is that fd_set by default uses limit (FD_SETSIZE) of 1024, unless FD_SETSIZE is set before including the <sys/select.h> header. The Qt4 source code contains some checks, but backtrace from GDB tells they're not enough. Instead of spending time on looking what's missed, I've just replaced select(2) with poll(2). Given that code actually shrunk, and I see no crashes anymore, I think it should go in.
I suppose this could be a security issue, as you could somehow trigger stack smashing, but I can't see anything harder than local DoS for now. But this could be different for some Qt-based apps. There are more select(2) calls which I'm willing to tweak before, though. This patch just fixes a problem I faced. Remember that Qt4 is EOL, so we don't have to bother about pushing those patches upstream. On the other side, Qt5 wants same treatment. Not sure that all platforms Qt5 runs on support poll(2) correctly, though. So, okay for this patch going in for now? -- WBR, Vadim Zhukov Index: Makefile =================================================================== RCS file: /cvs/ports/x11/qt4/Makefile,v retrieving revision 1.131 diff -u -p -r1.131 Makefile --- Makefile 6 Jan 2016 17:17:32 -0000 1.131 +++ Makefile 30 Jan 2016 19:46:21 -0000 @@ -24,7 +24,7 @@ PKGNAME-main = qt4-${PKGVERSION} PKGNAME-debug = qt4-debug-${PKGVERSION} FULLPKGNAME-html = qt4-html-${PKGVERSION} FULLPKGPATH-html = ${BASE_PKGPATH},-html -REVISION-main = 3 +REVISION-main = 4 # XXX qmake include parser is bogus DPB_PROPERTIES = parallel nojunk Index: patches/patch-src_network_socket_qnativesocketengine_unix_cpp =================================================================== RCS file: patches/patch-src_network_socket_qnativesocketengine_unix_cpp diff -N patches/patch-src_network_socket_qnativesocketengine_unix_cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-src_network_socket_qnativesocketengine_unix_cpp 30 Jan 2016 19:46:21 -0000 @@ -0,0 +1,78 @@ +$OpenBSD$ +Fix for cases of >1024 open files. +--- src/network/socket/qnativesocketengine_unix.cpp.orig Sat Jan 30 09:34:38 2016 ++++ src/network/socket/qnativesocketengine_unix.cpp Sat Jan 30 19:19:51 2016 +@@ -50,6 +50,7 @@ + #include <time.h> + #include <errno.h> + #include <fcntl.h> ++#include <poll.h> + #ifndef QT_NO_IPV6IFNAME + #include <net/if.h> + #endif +@@ -1068,48 +1069,31 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *da + + int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const + { +- fd_set fds; +- FD_ZERO(&fds); +- FD_SET(socketDescriptor, &fds); ++ struct pollfd pd; + +- struct timeval tv; +- tv.tv_sec = timeout / 1000; +- tv.tv_usec = (timeout % 1000) * 1000; +- +- int retval; +- if (selectForRead) +- retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); +- else +- retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); +- +- return retval; ++ memset(&pd, 0, sizeof(struct pollfd)); ++ pd.fd = socketDescriptor; ++ pd.events = selectForRead ? POLLIN : POLLHUP; ++ return poll(&pd, 1, timeout); + } + + int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) const + { +- fd_set fdread; +- FD_ZERO(&fdread); +- if (checkRead) +- FD_SET(socketDescriptor, &fdread); +- +- fd_set fdwrite; +- FD_ZERO(&fdwrite); +- if (checkWrite) +- FD_SET(socketDescriptor, &fdwrite); +- +- struct timeval tv; +- tv.tv_sec = timeout / 1000; +- tv.tv_usec = (timeout % 1000) * 1000; +- ++ struct pollfd pd; + int ret; +- ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); + +- if (ret <= 0) +- return ret; +- *selectForRead = FD_ISSET(socketDescriptor, &fdread); +- *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite); +- ++ memset(&pd, 0, sizeof(struct pollfd)); ++ pd.fd = socketDescriptor; ++ if (checkRead) ++ pd.events |= POLLIN; ++ if (checkWrite) ++ pd.events |= POLLOUT; ++ ret = poll(&pd, 1, timeout); ++ if (ret > 0) { ++ *selectForRead = ((pd.events & POLLIN) == POLLIN); ++ *selectForWrite = ((pd.events & POLLOUT) == POLLOUT); ++ } + return ret; + } +