]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Update to libevent HEAD as of 20110604, e40bafe796a8e544e9e54e247cb3aa30c95e06b0
authorDave Hart <hart@ntp.org>
Sun, 5 Jun 2011 11:23:00 +0000 (11:23 +0000)
committerDave Hart <hart@ntp.org>
Sun, 5 Jun 2011 11:23:00 +0000 (11:23 +0000)
Snapshot of libevent 2.1, as of 2.0.12-stable release.

bk: 4deb6714l4796Fn6rDPicqsu2TGkJQ

14 files changed:
sntp/libevent/ChangeLog
sntp/libevent/Makefile.am
sntp/libevent/README
sntp/libevent/buffer.c
sntp/libevent/configure.in
sntp/libevent/event.c
sntp/libevent/event_iocp.c
sntp/libevent/evport.c
sntp/libevent/evthread_win32.c
sntp/libevent/http.c
sntp/libevent/listener.c
sntp/libevent/select.c
sntp/libevent/test/regress_http.c
sntp/libevent/test/regress_ssl.c

index 9caf4064f7d9d4f1211d2b352902b4c42b51daf4..87f8db9531f6ddbb335e6baaeee59c7f8f594edc 100644 (file)
@@ -1,3 +1,43 @@
+Changes in version 2.0.13-stable (?? Jul 2011)
+
+
+
+Changes in version 2.0.12-stable (4 Jun 2011)
+BUGFIXES
+ o Fix a warn-and-fail bug in kqueue by providing kevent() room to report errors (28317a0)
+ o Fix an assert-inducing fencepost bug in the select backend (d90149d)
+ o Fix failing http assertion introducd in commit 0d6622e (0848814 Kevin Ko)
+ o Fix a bug that prevented us from configuring IPv6 nameservers. (74760f1)
+ o Prevent size_t overflow in evhttp_htmlescape. (06c51cd Mansour Moufid)
+ o Added several checks for under/overflow conditions in evhttp_handle_chunked_read (a279272 Mark Ellzey)
+ o Added overflow checks in evhttp_read_body and evhttp_get_body (84560fc Mark Ellzey)
+
+DOCUMENTATION:
+ o Add missing words to EVLOOP_NONBLOCK documentation (9556a7d)
+
+BUILD FIXES
+ o libssl depends on libcrypto, not the other way around. (274dd03 Peter Rosin)
+ o Libtool brings in the dependencies of libevent_openssl.la automatically (7b819f2 Peter Rosin)
+ o Use OPENSSL_LIBS in Makefile.am (292092e Sebastian Hahn)
+ o Move the win32 detection in configure.in (ceb03b9 Sebastian Hahn)
+ o Correctly detect openssl on windows (6619385 Sebastian Hahn)
+ o Fix a compile warning with zlib 1.2.4 and 1.2.5 (5786b91 Sebastian Hahn)
+ o Fix compilation with GCC 2, which had no __builtin_expect (09d39a1 Dave Hart)
+ o Fix new warnings from GCC 4.6 (06a714f)
+ o Link with -lshell32 and -ladvapi32 on Win32. (86090ee Peter Rosin)
+ o Make the tests build when OpenSSL is not available. (07c41be Peter Rosin)
+ o Bring in the compile script from automake, if needed. (f3c7a4c Peter Rosin)
+ o MSVC does not provide S_ISDIR, so provide it manually. (70be7d1 Peter Rosin)
+ o unistd.h and sys/time.h might not exist. (fe93022 Peter Rosin)
+ o Make sure TINYTEST_LOCAL is defined when building tinytest.c (8fa030c Peter Rosin)
+ o Fix winsock2.h #include issues with MSVC (3d768dc Peter Rosin)
+ o Use evutil_gettimeofday instead of relying on the system gettimeofday. (0de87fe Peter Rosin)
+ o Always use evutil_snprintf, even if OS provides it (d1b2d11 Sebastian Hahn)
+ o InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x0403. (816115a Peter Rosin)
+ o cygwin: make it possible to build DLLs (d54d3fc)
+
+
+
 Changes in version 2.0.11-stable (27 Apr 2011)
   [Autogenerated from the Git log, sorted and cleaned by hand.]
 BUGFIXES:
index 8511dc458c826f99384db2acba129d12d03361bc..dae46c247ca48c1c012616e174dc54d8638a4ca3 100644 (file)
@@ -35,6 +35,20 @@ RELEASE = -release 2.1
 VERSION_INFO = 1:0:0
 
 # History:          RELEASE    VERSION_INFO
+#  2.0.1-alpha --     2.0        1:0:0
+#  2.0.2-alpha --                2:0:0
+#  2.0.3-alpha --                2:0:0  (should have incremented; didn't.)
+#  2.0.4-alpha --                3:0:0
+#  2.0.5-beta  --                4:0:0
+#  2.0.6-rc    --     2.0        2:0:0
+#  2.0.7-rc    --     2.0        3:0:1
+#  2.0.8-rc    --     2.0        4:0:2
+#  2.0.9-rc    --     2.0        5:0:0 (ABI changed slightly)
+#  2.0.10-stable--    2.0        5:1:0 (No ABI change)
+#  2.0.11-stable--    2.0        6:0:1 (ABI changed, backward-compatible)
+#  2.0.12-stable--    2.0        6:1:1 (No ABI change)
+#
+# For Libevent 2.1:
 #  2.1.1-alpha --     2.1        1:0:0
 
 
@@ -160,7 +174,7 @@ CORE_SRC = event.c evthread.c buffer.c \
        evmap.c log.c evutil.c evutil_rand.c strlcpy.c $(SYS_SRC)
 EXTRA_SRC = event_tagging.c http.c evdns.c evrpc.c
 
-if BUILD_WIN32
+if BUILD_WITH_NO_UNDEFINED
 NO_UNDEFINED = -no-undefined
 MAYBE_CORE = libevent_core.la
 else
@@ -180,6 +194,7 @@ libevent_core_la_LDFLAGS = $(GENERIC_LDFLAGS)
 
 if PTHREADS
 libevent_pthreads_la_SOURCES = evthread_pthread.c
+libevent_pthreads_la_LIBADD = $(MAYBE_CORE)
 libevent_pthreads_la_LDFLAGS = $(GENERIC_LDFLAGS)
 endif
 
index 8044a98c4124b2f644dae0a2fc41c29eb8a25e99..bed2121a307818ca41642a1ba00113567f3d58ff 100644 (file)
@@ -104,6 +104,8 @@ fixing bugs:
   Claudio Jeker
   Evan Jones
   Phua Keat
+  Kevin Ko
+  Brian Koehmstedt
   Marko Kreen
   Valery Kyholodov
   Scott Lamb
@@ -122,6 +124,7 @@ fixing bugs:
   Andrey Matveev
   Caitlin Mercer
   Dagobert Michelsen
+  Mansour Moufid
   Felix Nawothnig
   Trond Norbye
   Linus Nordberg
@@ -136,7 +139,9 @@ fixing bugs:
   Dimitre Piskyulev
   Pavel Plesov
   Jon Poland
+  Robert Ransom
   Bert JW Regeer
+  Peter Rosin
   Hanna Schroeter
   Ralf Schmitt
   Mike Smellie
index 9d6ffc102b032dfef8b331b1856696bc35a74ee5..0a0be15b62582ce16d5b9bdd3d087397aec1adb9 100644 (file)
@@ -140,6 +140,8 @@ static int evbuffer_ptr_memcmp(const struct evbuffer *buf,
     const struct evbuffer_ptr *pos, const char *mem, size_t len);
 static struct evbuffer_chain *evbuffer_expand_singlechain(struct evbuffer *buf,
     size_t datlen);
+static int evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
+    size_t howfar);
 
 static struct evbuffer_chain *
 evbuffer_chain_new(size_t size)
@@ -1373,21 +1375,21 @@ evbuffer_search_eol(struct evbuffer *buffer,
                break;
        }
        case EVBUFFER_EOL_CRLF:
-               while (1) {
-                       if (evbuffer_find_eol_char(&it) < 0)
-                               goto done;
-                       if (evbuffer_getchr(&it) == '\n') {
-                               extra_drain = 1;
-                               break;
-                       } else if (!evbuffer_ptr_memcmp(
-                                   buffer, &it, "\r\n", 2)) {
-                               extra_drain = 2;
-                               break;
-                       } else {
-                               if (evbuffer_ptr_set(buffer, &it, 1,
-                                       EVBUFFER_PTR_ADD)<0)
-                                       goto done;
-                       }
+               /* Look for a LF ... */
+               if (evbuffer_strchr(&it, '\n') < 0)
+                       goto done;
+               extra_drain = 1;
+               /* ... optionally preceeded by a CR. */
+               if (it.pos < 1) break;
+               /* This potentially does an extra linear walk over the first
+                * few chains.  Probably, that's not too expensive unless you
+                * have a really pathological setup. */
+               memcpy(&it2, &it, sizeof(it));
+               if (evbuffer_ptr_subtract(buffer, &it2, 1)<0)
+                       break;
+               if (evbuffer_getchr(&it2) == '\r') {
+                       memcpy(&it, &it2, sizeof(it));
+                       extra_drain = 2;
                }
                break;
        case EVBUFFER_EOL_LF:
@@ -2275,6 +2277,29 @@ evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len)
        return search;
 }
 
+/* Subract <b>howfar</b> from the position of <b>pos</b> within
+ * <b>buf</b>. Returns 0 on success, -1 on failure.
+ *
+ * This isn't exposed yet, because of potential inefficiency issues.
+ * Maybe it should be. */
+static int
+evbuffer_ptr_subtract(struct evbuffer *buf, struct evbuffer_ptr *pos,
+    size_t howfar)
+{
+       if (howfar > (size_t)pos->pos)
+               return -1;
+       if (howfar <= pos->_internal.pos_in_chain) {
+               pos->_internal.pos_in_chain -= howfar;
+               pos->pos -= howfar;
+               return 0;
+       } else {
+               const size_t newpos = pos->pos - howfar;
+               /* Here's the inefficient part: it walks over the
+                * chains until we hit newpos. */
+               return evbuffer_ptr_set(buf, pos, newpos, EVBUFFER_PTR_SET);
+       }
+}
+
 int
 evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
     size_t position, enum evbuffer_ptr_how how)
@@ -2815,7 +2840,7 @@ evbuffer_add_file_segment(struct evbuffer *buf,
                        FILE_MAP_READ,
                        offset_rounded >> 32,
                        offset_rounded & 0xfffffffful,
-                       length);
+                       length + offset_remaining);
                if (data == NULL) {
                        mm_free(chain);
                        goto err;
index 0aa1fb9208aa540c0266c23ea199b9e6ebd21b76..774d4afb70d5bb3db4472b16ad951372903a44ad 100644 (file)
@@ -109,6 +109,19 @@ die horribly
        bwin32=false; AC_MSG_RESULT(no),
 )
 
+dnl - check if the macro __CYGWIN__ is defined on this compiler.
+dnl - (this is how we check for a cygwin version of GCC)
+AC_MSG_CHECKING(for CYGWIN)
+AC_TRY_COMPILE(,
+       [
+#ifndef __CYGWIN__
+die horribly
+#endif
+       ],
+       cygwin=true; AC_MSG_RESULT(yes),
+       cygwin=false; AC_MSG_RESULT(no),
+)
+
 AC_CHECK_HEADERS([zlib.h])
 
 if test "x$ac_cv_header_zlib_h" = "xyes"; then
@@ -242,6 +255,8 @@ if test "x$ac_cv_header_sys_sysctl_h" = "xyes"; then
 fi
 
 AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
+AM_CONDITIONAL(BUILD_CYGWIN, test x$cygwin = xtrue)
+AM_CONDITIONAL(BUILD_WITH_NO_UNDEFINED, test x$bwin32 = xtrue || test x$cygwin = xtrue)
 
 if test x$bwin32 = xtrue; then
    AC_SEARCH_LIBS([getservbyname],[ws2_32])
index 366d867deb6b0d130b56927599d6a7abed7dab69..62ec7f546044e81a827c4a01152b4ddc1f09091d 100644 (file)
@@ -604,6 +604,7 @@ event_base_new_with_config(const struct event_config *cfg)
        if (base->evbase == NULL) {
                event_warnx("%s: no event mechanism available",
                    __func__);
+               base->evsel = NULL;
                event_base_free(base);
                return NULL;
        }
@@ -825,6 +826,7 @@ event_reinit(struct event_base *base)
                base->th_notify_fd[0] = -1;
                base->th_notify_fd[1] = -1;
                event_debug_unassign(&base->th_notify);
+               base->th_notify_fn = NULL;
        }
 
        if (base->evsel->dealloc != NULL)
@@ -2696,8 +2698,10 @@ evthread_make_base_notifiable(struct event_base *base)
        if (!base)
                return -1;
 
-       if (base->th_notify_fd[0] >= 0)
+       if (base->th_notify_fn != NULL) {
+               /* The base is already notifiable: we're doing fine. */
                return 0;
+       }
 
 #if defined(_EVENT_HAVE_EVENTFD) && defined(_EVENT_HAVE_SYS_EVENTFD_H)
 #ifndef EFD_CLOEXEC
index fbeda703acac46042a22cede8bf95e8e1542f3f0..26ad64f2628040a61d46b5a4e33a9ab85315568b 100644 (file)
  */
 #include "evconfig-private.h"
 
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
 #include <winsock2.h>
 #include <windows.h>
 #include <process.h>
index 1b78960f4fc2e6ca43fc80005a28d54ae98ba878..f7f5597466be127cae57f8d99aa258c53ce38632 100644 (file)
 #include "evsignal-internal.h"
 #include "evmap-internal.h"
 
-/*
- * Default value for ed_nevents, which is the maximum file descriptor number we
- * can handle. If an event comes in for a file descriptor F > nevents, we will
- * grow the array of file descriptors, doubling its size.
- */
-#define DEFAULT_NFDS   16
-
-
-/*
- * EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on
- * any particular call. You can speed things up by increasing this, but it will
- * (obviously) require more memory.
- */
-#define EVENTS_PER_GETN 8
+#define INITIAL_EVENTS_PER_GETN 8
+#define MAX_EVENTS_PER_GETN 4096
 
 /*
  * Per-file-descriptor information about what events we're subscribed to. These
  */
 
 struct fd_info {
-       short fdi_what;         /* combinations of EV_READ and EV_WRITE */
+       /* combinations of EV_READ and EV_WRITE */
+       short fdi_what;
+       /* Index of this fd within ed_pending, plus 1.  Zero if this fd is
+        * not in ed_pending.  (The +1 is a hack so that memset(0) will set
+        * it to a nil index. */
+       int pending_idx_plus_1;
 };
 
 #define FDI_HAS_READ(fdi)  ((fdi)->fdi_what & EV_READ)
@@ -105,10 +98,15 @@ struct fd_info {
 
 struct evport_data {
        int             ed_port;        /* event port for system events  */
-       int             ed_nevents;     /* number of allocated fdi's     */
-       struct fd_info *ed_fds;         /* allocated fdi table           */
+       /* How many elements of ed_pending should we look at? */
+       int ed_npending;
+       /* How many elements are allocated in ed_pending and pevtlist? */
+       int ed_maxevents;
        /* fdi's that we need to reassoc */
-       int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
+       int *ed_pending;
+       /* storage space for incoming events. */ 
+       port_event_t *ed_pevtlist;
+       
 };
 
 static void*   evport_init(struct event_base *);
@@ -116,6 +114,7 @@ static int evport_add(struct event_base *, int fd, short old, short events, void
 static int evport_del(struct event_base *, int fd, short old, short events, void *);
 static int     evport_dispatch(struct event_base *, struct timeval *);
 static void    evport_dealloc(struct event_base *);
+static int     grow(struct evport_data *, int min_events);
 
 const struct eventop evportops = {
        "evport",
@@ -126,7 +125,7 @@ const struct eventop evportops = {
        evport_dealloc,
        1, /* need reinit */
        0, /* features */
-       0, /* fdinfo length */
+       sizeof(struct fd_info), /* fdinfo length */
 };
 
 /*
@@ -137,7 +136,6 @@ static void*
 evport_init(struct event_base *base)
 {
        struct evport_data *evpd;
-       int i;
 
        if (!(evpd = mm_calloc(1, sizeof(struct evport_data))))
                return (NULL);
@@ -147,24 +145,47 @@ evport_init(struct event_base *base)
                return (NULL);
        }
 
-       /*
-        * Initialize file descriptor structure
-        */
-       evpd->ed_fds = mm_calloc(DEFAULT_NFDS, sizeof(struct fd_info));
-       if (evpd->ed_fds == NULL) {
+       if (grow(evpd, INITIAL_EVENTS_PER_GETN) < 0) {
                close(evpd->ed_port);
                mm_free(evpd);
-               return (NULL);
+               return NULL;
        }
-       evpd->ed_nevents = DEFAULT_NFDS;
-       for (i = 0; i < EVENTS_PER_GETN; i++)
-               evpd->ed_pending[i] = -1;
+               
+       evpd->ed_npending = 0;
 
        evsig_init(base);
 
        return (evpd);
 }
 
+static int
+grow(struct evport_data *data, int min_events)
+{
+       int newsize;
+       int *new_pending;
+       port_event_t *new_pevtlist;
+       if (data->ed_maxevents) {
+               newsize = data->ed_maxevents;
+               do {
+                       newsize *= 2;
+               } while (newsize < min_events);
+       } else {
+               newsize = min_events;
+       }
+
+       new_pending = mm_realloc(data->ed_pending, sizeof(int)*newsize);
+       if (new_pending == NULL)
+               return -1;
+       data->ed_pending = new_pending;
+       new_pevtlist = mm_realloc(data->ed_pevtlist, sizeof(port_event_t)*newsize);
+       if (new_pevtlist == NULL)
+               return -1;
+       data->ed_pevtlist = new_pevtlist; 
+
+       data->ed_maxevents = newsize;
+       return 0;
+}
+
 #ifdef CHECK_INVARIANTS
 /*
  * Checks some basic properties about the evport_data structure. Because it
@@ -176,9 +197,7 @@ static void
 check_evportop(struct evport_data *evpd)
 {
        EVUTIL_ASSERT(evpd);
-       EVUTIL_ASSERT(evpd->ed_nevents > 0);
        EVUTIL_ASSERT(evpd->ed_port > 0);
-       EVUTIL_ASSERT(evpd->ed_fds > 0);
 }
 
 /*
@@ -194,7 +213,6 @@ check_event(port_event_t* pevt)
         * PORT_SOURCE_FD.
         */
        EVUTIL_ASSERT(pevt->portev_source == PORT_SOURCE_FD);
-       EVUTIL_ASSERT(pevt->portev_user == NULL);
 }
 
 #else
@@ -202,33 +220,6 @@ check_event(port_event_t* pevt)
 #define check_event(pevt)
 #endif /* CHECK_INVARIANTS */
 
-/*
- * Doubles the size of the allocated file descriptor array.
- */
-static int
-grow(struct evport_data *epdp, int factor)
-{
-       struct fd_info *tmp;
-       int oldsize = epdp->ed_nevents;
-       int newsize = factor * oldsize;
-       EVUTIL_ASSERT(factor > 1);
-
-       check_evportop(epdp);
-
-       tmp = mm_realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize);
-       if (NULL == tmp)
-               return -1;
-       epdp->ed_fds = tmp;
-       memset((char*) (epdp->ed_fds + oldsize), 0,
-           (newsize - oldsize)*sizeof(struct fd_info));
-       epdp->ed_nevents = newsize;
-
-       check_evportop(epdp);
-
-       return 0;
-}
-
-
 /*
  * (Re)associates the given file descriptor with the event port. The OS events
  * are specified (implicitly) from the fd_info struct.
@@ -240,7 +231,7 @@ reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd)
 
        if (sysevents != 0) {
                if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
-                                  fd, sysevents, NULL) == -1) {
+                                  fd, sysevents, fdip) == -1) {
                        event_warn("port_associate");
                        return (-1);
                }
@@ -261,12 +252,12 @@ evport_dispatch(struct event_base *base, struct timeval *tv)
 {
        int i, res;
        struct evport_data *epdp = base->evbase;
-       port_event_t pevtlist[EVENTS_PER_GETN];
+       port_event_t *pevtlist = epdp->ed_pevtlist;
 
        /*
         * port_getn will block until it has at least nevents events. It will
         * also return how many it's given us (which may be more than we asked
-        * for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
+        * for, as long as it's less than our maximum (ed_maxevents)) in
         * nevents.
         */
        int nevents = 1;
@@ -289,22 +280,25 @@ evport_dispatch(struct event_base *base, struct timeval *tv)
         * last time which need reassociation. See comment at the end of the
         * loop below.
         */
-       for (i = 0; i < EVENTS_PER_GETN; ++i) {
+       for (i = 0; i < epdp->ed_npending; ++i) {
                struct fd_info *fdi = NULL;
-               if (epdp->ed_pending[i] != -1) {
-                       fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
+               const int fd = epdp->ed_pending[i];
+               if (fd != -1) {
+                       /* We might have cleared out this event; we need
+                        * to be sure that it's still set. */
+                       fdi = evmap_io_get_fdinfo(&base->io, fd);
                }
 
                if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
-                       int fd = epdp->ed_pending[i];
                        reassociate(epdp, fdi, fd);
-                       epdp->ed_pending[i] = -1;
+//                     epdp->ed_pending[i] = -1;
+                       fdi->pending_idx_plus_1 = 0;
                }
        }
 
        EVBASE_RELEASE_LOCK(base, th_base_lock);
 
-       res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
+       res = port_getn(epdp->ed_port, pevtlist, epdp->ed_maxevents,
            (unsigned int *) &nevents, ts_p);
 
        EVBASE_ACQUIRE_LOCK(base, th_base_lock);
@@ -324,13 +318,15 @@ evport_dispatch(struct event_base *base, struct timeval *tv)
        event_debug(("%s: port_getn reports %d events", __func__, nevents));
 
        for (i = 0; i < nevents; ++i) {
-               struct fd_info *fdi;
                port_event_t *pevt = &pevtlist[i];
                int fd = (int) pevt->portev_object;
+               struct fd_info *fdi = pevt->portev_user;
+               //EVUTIL_ASSERT(evmap_io_get_fdinfo(&base->io, fd) == fdi);
 
                check_evportop(epdp);
                check_event(pevt);
                epdp->ed_pending[i] = fd;
+               fdi->pending_idx_plus_1 = i + 1;
 
                /*
                 * Figure out what kind of event it was
@@ -352,11 +348,16 @@ evport_dispatch(struct event_base *base, struct timeval *tv)
                if (pevt->portev_events & (POLLERR|POLLHUP|POLLNVAL))
                        res |= EV_READ|EV_WRITE;
 
-               EVUTIL_ASSERT(epdp->ed_nevents > fd);
-               fdi = &(epdp->ed_fds[fd]);
-
                evmap_io_active(base, fd, res);
        } /* end of all events gotten */
+       epdp->ed_npending = nevents;
+
+       if (nevents == epdp->ed_maxevents &&
+           epdp->ed_maxevents < MAX_EVENTS_PER_GETN) {
+               /* we used all the space this time.  We should be ready
+                * for more events next time around. */
+               grow(epdp, epdp->ed_maxevents * 2);
+       }
 
        check_evportop(epdp);
 
@@ -373,27 +374,10 @@ static int
 evport_add(struct event_base *base, int fd, short old, short events, void *p)
 {
        struct evport_data *evpd = base->evbase;
-       struct fd_info *fdi;
-       int factor;
-       (void)p;
+       struct fd_info *fdi = p;
 
        check_evportop(evpd);
 
-       /*
-        * If necessary, grow the file descriptor info table
-        */
-
-       factor = 1;
-       while (fd >= factor * evpd->ed_nevents)
-               factor *= 2;
-
-       if (factor > 1) {
-               if (-1 == grow(evpd, factor)) {
-                       return (-1);
-               }
-       }
-
-       fdi = &evpd->ed_fds[fd];
        fdi->fdi_what |= events;
 
        return reassociate(evpd, fdi, fd);
@@ -407,29 +391,12 @@ static int
 evport_del(struct event_base *base, int fd, short old, short events, void *p)
 {
        struct evport_data *evpd = base->evbase;
-       struct fd_info *fdi;
-       int i;
-       int associated = 1;
-       (void)p;
+       struct fd_info *fdi = p;
+       int associated = ! fdi->pending_idx_plus_1;
 
        check_evportop(evpd);
 
-       if (evpd->ed_nevents < fd) {
-               return (-1);
-       }
-
-       for (i = 0; i < EVENTS_PER_GETN; ++i) {
-               if (evpd->ed_pending[i] == fd) {
-                       associated = 0;
-                       break;
-               }
-       }
-
-       fdi = &evpd->ed_fds[fd];
-       if (events & EV_READ)
-               fdi->fdi_what &= ~EV_READ;
-       if (events & EV_WRITE)
-               fdi->fdi_what &= ~EV_WRITE;
+       fdi->fdi_what &= ~(events &(EV_READ|EV_WRITE));
 
        if (associated) {
                if (!FDI_HAS_EVENTS(fdi) &&
@@ -449,7 +416,10 @@ evport_del(struct event_base *base, int fd, short old, short events, void *p)
                }
        } else {
                if ((fdi->fdi_what & (EV_READ|EV_WRITE)) == 0) {
+                       const int i = fdi->pending_idx_plus_1 - 1;
+                       EVUTIL_ASSERT(evpd->ed_pending[i] == fd);
                        evpd->ed_pending[i] = -1;
+                       fdi->pending_idx_plus_1 = 0;
                }
        }
        return 0;
@@ -465,7 +435,10 @@ evport_dealloc(struct event_base *base)
 
        close(evpd->ed_port);
 
-       if (evpd->ed_fds)
-               mm_free(evpd->ed_fds);
+       if (evpd->ed_pending)
+               mm_free(evpd->ed_pending);
+       if (evpd->ed_pevtlist)
+               mm_free(evpd->ed_pevtlist);
+
        mm_free(evpd);
 }
index 7bb97bf96bffc7cacb6b28d31d2b4efa8467ec25..2dcd70c2022fcc97be1367fae0fdd1e7426fc745 100644 (file)
 #include "evconfig-private.h"
 
 #ifdef _WIN32
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
 #include <winsock2.h>
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
index ac92898014714c34e0aa6e0fc6bb2ef4afd8b7bd..540c21d02b998f2bd9e5dbf0fdbbe104965f3a77 100644 (file)
@@ -841,9 +841,23 @@ evhttp_connection_done(struct evhttp_connection *evcon)
 static enum message_read_status
 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
 {
-       ev_ssize_t len;
+       if (req == NULL || buf == NULL) {
+           return DATA_CORRUPTED;
+       }
+
+       while (1) {
+               size_t buflen;
+
+               if ((buflen = evbuffer_get_length(buf)) == 0) {
+                       break;
+               }
+
+               /* evbuffer_get_length returns size_t, but len variable is ssize_t,
+                * check for overflow conditions */
+               if (buflen > EV_SSIZE_MAX) {
+                       return DATA_CORRUPTED;
+               }
 
-       while ((len = evbuffer_get_length(buf)) > 0) {
                if (req->ntoread < 0) {
                        /* Read chunk size */
                        ev_int64_t ntoread;
@@ -866,11 +880,18 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
                                /* could not get chunk size */
                                return (DATA_CORRUPTED);
                        }
+
+                       /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
+                       if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
+                           return DATA_CORRUPTED;
+                       }
+
                        if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
                                /* failed body length test */
                                event_debug(("Request body is too long"));
                                return (DATA_TOO_LONG);
                        }
+
                        req->body_size += (size_t)ntoread;
                        req->ntoread = ntoread;
                        if (req->ntoread == 0) {
@@ -880,12 +901,17 @@ evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
                        continue;
                }
 
+               /* req->ntoread is signed int64, len is ssize_t, based on arch,
+                * ssize_t could only be 32b, check for these conditions */
+               if (req->ntoread > EV_SSIZE_MAX) {
+                       return DATA_CORRUPTED;
+               }
+
                /* don't have enough to complete a chunk; wait for more */
-               if (len < req->ntoread)
+               if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
                        return (MORE_DATA_EXPECTED);
 
                /* Completed chunk */
-               /* XXXX fixme: what if req->ntoread is > SIZE_T_MAX? */
                evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
                req->ntoread = -1;
                if (req->chunk_cb != NULL) {
@@ -953,13 +979,19 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
                }
        } else if (req->ntoread < 0) {
                /* Read until connection close. */
+               if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
+                       evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
+                       return;
+               }
+
                req->body_size += evbuffer_get_length(buf);
                evbuffer_add_buffer(req->input_buffer, buf);
-       } else if (req->chunk_cb != NULL ||
-           evbuffer_get_length(buf) >= (size_t)req->ntoread) {
+       } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
+               /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
                /* We've postponed moving the data until now, but we're
                 * about to use it. */
                size_t n = evbuffer_get_length(buf);
+
                if (n > (size_t) req->ntoread)
                        n = (size_t) req->ntoread;
                req->ntoread -= n;
@@ -970,6 +1002,7 @@ evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
        if (req->body_size > req->evcon->max_body_size ||
            (!req->chunked && req->ntoread >= 0 &&
                (size_t)req->ntoread > req->evcon->max_body_size)) {
+               /* XXX: The above casted comparison must checked for overflow */
                /* failed body length test */
                event_debug(("Request body is too long"));
                evhttp_connection_fail(evcon,
@@ -2000,11 +2033,12 @@ evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
                                   no, we should respond with an error. For
                                   now, just optimistically tell the client to
                                   send their message body. */
-                               if (req->ntoread > 0 &&
-                                   (size_t)req->ntoread > req->evcon->max_body_size) {
-                                       evhttp_send_error(req, HTTP_ENTITYTOOLARGE,
-                                                         NULL);
-                                       return;
+                               if (req->ntoread > 0) {
+                                       /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */ 
+                                       if ((req->evcon->max_body_size <= EV_INT64_MAX) && (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
+                                               evhttp_send_error(req, HTTP_ENTITYTOOLARGE, NULL);
+                                               return;
+                                       }
                                }
                                if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
                                        evhttp_send_continue(evcon, req);
index aaceaae742a53bb5b8e0ada4a2e7f3310aaa9b66..7f80338288b8ae265467b5b5e75c57ab66a2d4b1 100644 (file)
 #include <sys/types.h>
 
 #ifdef _WIN32
+#ifndef _WIN32_WINNT
+/* Minimum required for InitializeCriticalSectionAndSpinCount */
+#define _WIN32_WINNT 0x0403
+#endif
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #include <mswsock.h>
index b2a373324114991292f38e091c5ea14fd331d85f..e418261df6ffdcd377f50930a64f21447ec7b9e6 100644 (file)
@@ -173,9 +173,9 @@ select_dispatch(struct event_base *base, struct timeval *tv)
        event_debug(("%s: select reports %d", __func__, res));
 
        check_selectop(sop);
-       i = random() % (nfds+1);
-       for (j = 0; j <= nfds; ++j) {
-               if (++i >= nfds+1)
+       i = random() % nfds;
+       for (j = 0; j < nfds; ++j) {
+               if (++i >= nfds)
                        i = 0;
                res = 0;
                if (FD_ISSET(i, sop->event_readset_out))
index b232469c8eb1130d5d66be3471d1f44c4c78b0f3..48ed525e0a2241bab88bc6d078cae9e815770c03 100644 (file)
@@ -3040,9 +3040,9 @@ http_connection_fail_test(void *arg)
        evhttp_free(http);
        http = NULL;
 
-       /* Pick an unroutable address.  The limited broadcast address should do
-        * when working with TCP. */
-       evcon = evhttp_connection_base_new(data->base, NULL, "255.255.255.255", 80);
+       /* Pick an unroutable address.  This administratively scoped multicast
+       * address should do when working with TCP. */
+       evcon = evhttp_connection_base_new(data->base, NULL, "239.10.20.30", 80);
        tt_assert(evcon);
 
        /*
index c2f7a14da5a45973ab6390f6365a4cb4b2c4d3a6..6bac30e413297ecbc5ccb44c94e5efe7f682194f 100644 (file)
@@ -30,6 +30,7 @@
 #endif
 
 #ifndef _WIN32
+#include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #endif