aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2018-06-13 17:49:38 +0200
committerSverker Eriksson <[email protected]>2018-06-13 17:49:38 +0200
commitac9ed8e2575dca9e5ebe2f7af00dfe4da87b1bcc (patch)
tree5b89000dca5c495c78440cb9538805fba7da6757
parente80ce8436cbc754221c40c04702c317e9779fd79 (diff)
downloadotp-ac9ed8e2575dca9e5ebe2f7af00dfe4da87b1bcc.tar.gz
otp-ac9ed8e2575dca9e5ebe2f7af00dfe4da87b1bcc.tar.bz2
otp-ac9ed8e2575dca9e5ebe2f7af00dfe4da87b1bcc.zip
erts: Fix MacOS pollset bug
that could cause clearing of fd-bits past allocated bit-vectors. Bug introduced on master by 988f5f5e8061ce2e135a314ca782788eda478a06
-rw-r--r--erts/emulator/sys/common/erl_poll.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index ced8a4a2a7..e3f27caea7 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -141,12 +141,26 @@ typedef struct {
size_t sz;
fd_set* ptr;
}ERTS_fd_set;
-# define ERTS_FD_CLR(fd, fds) FD_CLR((fd), (fds)->ptr)
-# define ERTS_FD_SET(fd, fds) FD_SET((fd), (fds)->ptr)
-# define ERTS_FD_ISSET(fd,fds) FD_ISSET((fd), (fds)->ptr)
+
# define ERTS_FD_ZERO(fds) memset((fds)->ptr, 0, (fds)->sz)
# define ERTS_FD_SIZE(n) ((((n)+NFDBITS-1)/NFDBITS)*sizeof(fd_mask))
+static ERTS_INLINE void ERTS_FD_CLR(int fd, ERTS_fd_set *fds)
+{
+ ASSERT(ERTS_FD_SIZE(fd+1) <= fds->sz);
+ FD_CLR(fd, fds->ptr);
+}
+static ERTS_INLINE void ERTS_FD_SET(int fd, ERTS_fd_set *fds)
+{
+ ASSERT(ERTS_FD_SIZE(fd+1) <= fds->sz);
+ FD_SET(fd, fds->ptr);
+}
+static ERTS_INLINE int ERTS_FD_ISSET(int fd, ERTS_fd_set *fds)
+{
+ ASSERT(ERTS_FD_SIZE(fd+1) <= fds->sz);
+ return FD_ISSET(fd, fds->ptr);
+}
+
static void ERTS_FD_COPY(ERTS_fd_set *src, ERTS_fd_set *dst)
{
if (dst->sz != src->sz) {
@@ -626,8 +640,15 @@ ensure_select_fds(int fd, ERTS_fd_set* in, ERTS_fd_set* out)
grow_select_fds(fd, out);
}
}
+static ERTS_INLINE int
+check_select_fds(int fd, ERTS_fd_set* in, ERTS_fd_set* out)
+{
+ ASSERT(in->sz == out->sz);
+ return (ERTS_FD_SIZE(fd+1) <= in->sz);
+}
#else
# define ensure_select_fds(fd, in, out) do {} while(0)
+# define check_select_fds(fd, in, out) (1)
#endif /* _DARWIN_UNLIMITED_SELECT */
#if !ERTS_POLL_USE_CONCURRENT_UPDATE
@@ -1085,8 +1106,10 @@ static int update_pollset(ErtsPollSet *ps, ErtsPollResFd pr[], int fd)
res++;
}
- ERTS_FD_CLR(fd, &ps->input_fds);
- ERTS_FD_CLR(fd, &ps->output_fds);
+ if (check_select_fds(fd, &ps->input_fds, &ps->output_fds)) {
+ ERTS_FD_CLR(fd, &ps->input_fds);
+ ERTS_FD_CLR(fd, &ps->output_fds);
+ }
if (ps->fds_status[fd].used_events) {
erts_atomic_dec_nob(&ps->no_of_user_fds);