mirror of
https://github.com/glfw/glfw.git
synced 2025-06-15 12:12:16 +00:00
X11: Fix segfault when _glfw.x11.display is higher than 1024
FD_SETSIZE is hardcoded to 1024 in glibc. See the bugs section of the select call for more info. In some cases, it is possible for _glfw.x11.display to be larger than FD_SETSIZE, causing a segfault or buffer overflow. Replacing select() with poll() seems to be the recommended solution: - https://www.man7.org/linux/man-pages/man2/select.2.html#BUGS - https://access.redhat.com/solutions/488623 - https://stackoverflow.com/questions/7976388/increasing-limit-of-fd-setsize-and-select/7977082#7977082
This commit is contained in:
parent
df8d7bc892
commit
57ab8acc0e
@ -41,6 +41,10 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#include <poll.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// Action for EWMH client messages
|
// Action for EWMH client messages
|
||||||
#define _NET_WM_STATE_REMOVE 0
|
#define _NET_WM_STATE_REMOVE 0
|
||||||
#define _NET_WM_STATE_ADD 1
|
#define _NET_WM_STATE_ADD 1
|
||||||
@ -63,31 +67,47 @@
|
|||||||
//
|
//
|
||||||
static GLFWbool waitForEvent(double* timeout)
|
static GLFWbool waitForEvent(double* timeout)
|
||||||
{
|
{
|
||||||
fd_set fds;
|
|
||||||
const int fd = ConnectionNumber(_glfw.x11.display);
|
const int fd = ConnectionNumber(_glfw.x11.display);
|
||||||
int count = fd + 1;
|
|
||||||
|
|
||||||
|
int count;
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
if (_glfw.linjs.inotify > fd)
|
struct pollfd pfd[2];
|
||||||
count = _glfw.linjs.inotify + 1;
|
#else
|
||||||
|
fd_set fds;
|
||||||
|
count = fd + 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
|
pfd[0].fd = fd;
|
||||||
|
pfd[0].events = POLLIN;
|
||||||
|
if (_glfw.linjs.inotify > 0)
|
||||||
|
{
|
||||||
|
count = 2;
|
||||||
|
pfd[1].fd = _glfw.linjs.inotify;
|
||||||
|
pfd[1].events = POLLIN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
count = 1;
|
||||||
|
#else
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
FD_SET(fd, &fds);
|
FD_SET(fd, &fds);
|
||||||
#if defined(__linux__)
|
|
||||||
if (_glfw.linjs.inotify > 0)
|
|
||||||
FD_SET(_glfw.linjs.inotify, &fds);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (timeout)
|
if (timeout)
|
||||||
{
|
{
|
||||||
const long seconds = (long) *timeout;
|
const long seconds = (long) *timeout;
|
||||||
const long microseconds = (long) ((*timeout - seconds) * 1e6);
|
const long microseconds = (long) ((*timeout - seconds) * 1e6);
|
||||||
struct timeval tv = { seconds, microseconds };
|
|
||||||
const uint64_t base = _glfwPlatformGetTimerValue();
|
const uint64_t base = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
int timeout_ms = (seconds * 1000) + (microseconds / 1000);
|
||||||
|
const int result = poll(pfd, count, timeout_ms);
|
||||||
|
#else
|
||||||
|
struct timeval tv = { seconds, microseconds };
|
||||||
const int result = select(count, &fds, NULL, NULL, &tv);
|
const int result = select(count, &fds, NULL, NULL, &tv);
|
||||||
|
#endif
|
||||||
const int error = errno;
|
const int error = errno;
|
||||||
|
|
||||||
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
*timeout -= (_glfwPlatformGetTimerValue() - base) /
|
||||||
@ -98,7 +118,11 @@ static GLFWbool waitForEvent(double* timeout)
|
|||||||
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
|
if ((result == -1 && error == EINTR) || *timeout <= 0.0)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
#if defined(__linux__)
|
||||||
|
else if (poll(pfd, count, 0) != -1 || errno != EINTR)
|
||||||
|
#else
|
||||||
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
|
else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
|
||||||
|
#endif
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user