[DRE-commits] [ruby-eventmachine] 01/02: Fix remotely triggerable crash due to FD handling
Balint Reczey
rbalint at moszumanska.debian.org
Tue Jun 28 01:23:49 UTC 2016
This is an automated email from the git hooks/post-receive script.
rbalint pushed a commit to branch jessie
in repository ruby-eventmachine.
commit bce6a9e58391fc0df9f604b1620fee229729bd6f
Author: Balint Reczey <balint at balintreczey.hu>
Date: Tue Jun 28 02:29:27 2016 +0200
Fix remotely triggerable crash due to FD handling
---
...e-ruby-select-api-with-expandable-fd-sets.patch | 217 +++++++++++++++++++++
...d-stubs-with-warnings-for-1.8.7-and-1.9.0.patch | 44 +++++
...-comment-about-where-the-macros-came-from.patch | 26 +++
debian/patches/series | 3 +
4 files changed, 290 insertions(+)
diff --git a/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch b/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch
new file mode 100644
index 0000000..cb2f61a
--- /dev/null
+++ b/debian/patches/0001-use-ruby-select-api-with-expandable-fd-sets.patch
@@ -0,0 +1,217 @@
+From eab3baaba75c8c9e549aea54d3b356ab287a57b0 Mon Sep 17 00:00:00 2001
+From: Patrick Reynolds <patrick.reynolds at github.com>
+Date: Tue, 11 Mar 2014 16:01:25 -0500
+Subject: [PATCH 1/3] use ruby select api with expandable fd sets
+
+Conflicts:
+ ext/em.h
+---
+ ext/em.cpp | 54 +++++++++++++++++++++++++-------------------------
+ ext/em.h | 10 +++++-----
+ tests/test_many_fds.rb | 22 ++++++++++++++++++++
+ 3 files changed, 54 insertions(+), 32 deletions(-)
+ create mode 100644 tests/test_many_fds.rb
+
+diff --git a/ext/em.cpp b/ext/em.cpp
+index 670da31..6a3a2ef 100644
+--- a/ext/em.cpp
++++ b/ext/em.cpp
+@@ -524,12 +524,12 @@ void EventMachine_t::_RunEpollOnce()
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ if ((ret = rb_wait_for_single_fd(epfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
+ #else
+- fd_set fdreads;
++ rb_fdset_t fdreads;
+
+- FD_ZERO(&fdreads);
+- FD_SET(epfd, &fdreads);
++ rb_fd_init(&fdreads);
++ rb_fd_set(epfd, &fdreads);
+
+- if ((ret = rb_thread_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
++ if ((ret = rb_thread_fd_select(epfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ #endif
+ if (ret == -1) {
+ assert(errno != EINVAL);
+@@ -601,12 +601,12 @@ void EventMachine_t::_RunKqueueOnce()
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ if ((ret = rb_wait_for_single_fd(kqfd, RB_WAITFD_IN|RB_WAITFD_PRI, &tv)) < 1) {
+ #else
+- fd_set fdreads;
++ rb_fdset_t fdreads;
+
+- FD_ZERO(&fdreads);
+- FD_SET(kqfd, &fdreads);
++ rb_fd_init(&fdreads);
++ rb_fd_set(kqfd, &fdreads);
+
+- if ((ret = rb_thread_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
++ if ((ret = rb_thread_fd_select(kqfd + 1, &fdreads, NULL, NULL, &tv)) < 1) {
+ #endif
+ if (ret == -1) {
+ assert(errno != EINVAL);
+@@ -792,9 +792,9 @@ SelectData_t::SelectData_t
+ SelectData_t::SelectData_t()
+ {
+ maxsocket = 0;
+- FD_ZERO (&fdreads);
+- FD_ZERO (&fdwrites);
+- FD_ZERO (&fderrors);
++ rb_fd_init (&fdreads);
++ rb_fd_init (&fdwrites);
++ rb_fd_init (&fderrors);
+ }
+
+
+@@ -807,7 +807,7 @@ _SelectDataSelect
+ static VALUE _SelectDataSelect (void *v)
+ {
+ SelectData_t *sd = (SelectData_t*)v;
+- sd->nSockets = select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
++ sd->nSockets = rb_fd_select (sd->maxsocket+1, &(sd->fdreads), &(sd->fdwrites), &(sd->fderrors), &(sd->tv));
+ return Qnil;
+ }
+ #endif
+@@ -848,9 +848,9 @@ void EventMachine_t::_RunSelectOnce()
+
+ SelectData_t SelectData;
+ /*
+- fd_set fdreads, fdwrites;
+- FD_ZERO (&fdreads);
+- FD_ZERO (&fdwrites);
++ rb_fdset_t fdreads, fdwrites;
++ rb_fd_init (&fdreads);
++ rb_fd_init (&fdwrites);
+
+ int maxsocket = 0;
+ */
+@@ -860,7 +860,7 @@ void EventMachine_t::_RunSelectOnce()
+ // running on localhost with a randomly-chosen port. (*Puke*)
+ // Windows has a version of the Unix pipe() library function, but it doesn't
+ // give you back descriptors that are selectable.
+- FD_SET (LoopBreakerReader, &(SelectData.fdreads));
++ rb_fd_set (LoopBreakerReader, &(SelectData.fdreads));
+ if (SelectData.maxsocket < LoopBreakerReader)
+ SelectData.maxsocket = LoopBreakerReader;
+
+@@ -875,15 +875,15 @@ void EventMachine_t::_RunSelectOnce()
+ assert (sd != INVALID_SOCKET);
+
+ if (ed->SelectForRead())
+- FD_SET (sd, &(SelectData.fdreads));
++ rb_fd_set (sd, &(SelectData.fdreads));
+ if (ed->SelectForWrite())
+- FD_SET (sd, &(SelectData.fdwrites));
++ rb_fd_set (sd, &(SelectData.fdwrites));
+
+ #ifdef OS_WIN32
+ /* 21Sep09: on windows, a non-blocking connect() that fails does not come up as writable.
+ Instead, it is added to the error set. See http://www.mail-archive.com/openssl-users@openssl.org/msg58500.html
+ */
+- FD_SET (sd, &(SelectData.fderrors));
++ rb_fd_set (sd, &(SelectData.fderrors));
+ #endif
+
+ if (SelectData.maxsocket < sd)
+@@ -918,15 +918,15 @@ void EventMachine_t::_RunSelectOnce()
+ continue;
+ assert (sd != INVALID_SOCKET);
+
+- if (FD_ISSET (sd, &(SelectData.fdwrites)))
++ if (rb_fd_isset (sd, &(SelectData.fdwrites)))
+ ed->Write();
+- if (FD_ISSET (sd, &(SelectData.fdreads)))
++ if (rb_fd_isset (sd, &(SelectData.fdreads)))
+ ed->Read();
+- if (FD_ISSET (sd, &(SelectData.fderrors)))
++ if (rb_fd_isset (sd, &(SelectData.fderrors)))
+ ed->HandleError();
+ }
+
+- if (FD_ISSET (LoopBreakerReader, &(SelectData.fdreads)))
++ if (rb_fd_isset (LoopBreakerReader, &(SelectData.fdreads)))
+ _ReadLoopBreaker();
+ }
+ else if (s < 0) {
+@@ -964,11 +964,11 @@ void EventMachine_t::_CleanBadDescriptors()
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+- fd_set fds;
+- FD_ZERO(&fds);
+- FD_SET(sd, &fds);
++ rb_fdset_t fds;
++ rb_fd_init(&fds);
++ rb_fd_set(sd, &fds);
+
+- int ret = select(sd + 1, &fds, NULL, NULL, &tv);
++ int ret = rb_fd_select(sd + 1, &fds, NULL, NULL, &tv);
+
+ if (ret == -1) {
+ if (errno == EBADF)
+diff --git a/ext/em.h b/ext/em.h
+index df68ec1..ff7c26c 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -22,7 +22,7 @@ See the file COPYING for complete licensing information.
+
+ #ifdef BUILD_FOR_RUBY
+ #include <ruby.h>
+- #define EmSelect rb_thread_select
++ #define EmSelect rb_thread_fd_select
+
+ #ifdef HAVE_RB_WAIT_FOR_SINGLE_FD
+ #include <ruby/io.h>
+@@ -57,7 +57,7 @@ See the file COPYING for complete licensing information.
+ #define RSTRING_LENINT(str) RSTRING_LEN(str)
+ #endif
+ #else
+- #define EmSelect select
++ #define EmSelect rb_fd_select
+ #endif
+
+ class EventableDescriptor;
+@@ -233,9 +233,9 @@ struct SelectData_t
+ int _Select();
+
+ int maxsocket;
+- fd_set fdreads;
+- fd_set fdwrites;
+- fd_set fderrors;
++ rb_fdset_t fdreads;
++ rb_fdset_t fdwrites;
++ rb_fdset_t fderrors;
+ timeval tv;
+ int nSockets;
+ };
+diff --git a/tests/test_many_fds.rb b/tests/test_many_fds.rb
+new file mode 100644
+index 0000000..74dc926
+--- /dev/null
++++ b/tests/test_many_fds.rb
+@@ -0,0 +1,22 @@
++require 'em_test_helper'
++require 'socket'
++
++class TestManyFDs < Test::Unit::TestCase
++ def setup
++ @port = next_port
++ end
++
++ def test_connection_class_cache
++ mod = Module.new
++ a = nil
++ Process.setrlimit(Process::RLIMIT_NOFILE,4096);
++ EM.run {
++ EM.start_server '127.0.0.1', @port, mod
++ 1100.times do
++ a = EM.connect '127.0.0.1', @port, mod
++ assert_kind_of EM::Connection, a
++ end
++ EM.stop
++ }
++ end
++end
+--
+2.1.4
+
diff --git a/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch b/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch
new file mode 100644
index 0000000..0eccb55
--- /dev/null
+++ b/debian/patches/0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch
@@ -0,0 +1,44 @@
+From ef5dac813ef3d10423ec7ca8255eea6d873278f1 Mon Sep 17 00:00:00 2001
+From: Patrick Reynolds <patrick.reynolds at github.com>
+Date: Wed, 12 Mar 2014 00:15:41 -0500
+Subject: [PATCH 2/3] add stubs with warnings for 1.8.7 and 1.9.0
+
+---
+ ext/em.h | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/ext/em.h b/ext/em.h
+index ff7c26c..5b9279d 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -60,6 +60,27 @@ See the file COPYING for complete licensing information.
+ #define EmSelect rb_fd_select
+ #endif
+
++#ifndef rb_fd_max
++#define fd_check(n) (((n) < FD_SETSIZE) ? 1 : 0*fprintf(stderr, "fd %d too large for select\n", (n)))
++typedef fd_set rb_fdset_t;
++#define rb_fd_zero(f) FD_ZERO(f)
++#define rb_fd_set(n, f) do { if (fd_check(n)) FD_SET((n), (f)); } while(0)
++#define rb_fd_clr(n, f) do { if (fd_check(n)) FD_CLR((n), (f)); } while(0)
++#define rb_fd_isset(n, f) (fd_check(n) ? FD_ISSET((n), (f)) : 0)
++#define rb_fd_copy(d, s, n) (*(d) = *(s))
++#define rb_fd_dup(d, s) (*(d) = *(s))
++#define rb_fd_resize(n, f) ((void)(f))
++#define rb_fd_ptr(f) (f)
++#define rb_fd_init(f) FD_ZERO(f)
++#define rb_fd_init_copy(d, s) (*(d) = *(s))
++#define rb_fd_term(f) ((void)(f))
++#define rb_fd_max(f) FD_SETSIZE
++#define rb_fd_select(n, rfds, wfds, efds, timeout) \
++ select(fd_check((n)-1) ? (n) : FD_SETSIZE, (rfds), (wfds), (efds), (timeout))
++#define rb_thread_fd_select(n, rfds, wfds, efds, timeout) \
++ rb_thread_select(fd_check((n)-1) ? (n) : FD_SETSIZE, (rfds), (wfds), (efds), (timeout))
++#endif
++
+ class EventableDescriptor;
+ class InotifyDescriptor;
+
+--
+2.1.4
+
diff --git a/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch b/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch
new file mode 100644
index 0000000..a70bf60
--- /dev/null
+++ b/debian/patches/0003-add-comment-about-where-the-macros-came-from.patch
@@ -0,0 +1,26 @@
+From 81b673a5a0cd7f96ad7c7bbc6052bbed30b0a2a5 Mon Sep 17 00:00:00 2001
+From: Patrick Reynolds <patrick.reynolds at github.com>
+Date: Wed, 21 Jan 2015 22:34:43 -0600
+Subject: [PATCH 3/3] add comment about where the macros came from
+
+---
+ ext/em.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/ext/em.h b/ext/em.h
+index 5b9279d..05d4310 100644
+--- a/ext/em.h
++++ b/ext/em.h
+@@ -62,6 +62,9 @@ See the file COPYING for complete licensing information.
+
+ #ifndef rb_fd_max
+ #define fd_check(n) (((n) < FD_SETSIZE) ? 1 : 0*fprintf(stderr, "fd %d too large for select\n", (n)))
++// These definitions are cribbed from include/ruby/intern.h in Ruby 1.9.3,
++// with this change: any macros that read or write the nth element of an
++// fdset first call fd_check to make sure n is in bounds.
+ typedef fd_set rb_fdset_t;
+ #define rb_fd_zero(f) FD_ZERO(f)
+ #define rb_fd_set(n, f) do { if (fd_check(n)) FD_SET((n), (f)); } while(0)
+--
+2.1.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 4b9635e..cd00754 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,4 @@
skip_tests_using_network.patch
+0001-use-ruby-select-api-with-expandable-fd-sets.patch
+0002-add-stubs-with-warnings-for-1.8.7-and-1.9.0.patch
+0003-add-comment-about-where-the-macros-came-from.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-eventmachine.git
More information about the Pkg-ruby-extras-commits
mailing list