From: Dave Hart Date: Sun, 5 Jun 2011 11:23:00 +0000 (+0000) Subject: Update to libevent HEAD as of 20110604, e40bafe796a8e544e9e54e247cb3aa30c95e06b0 X-Git-Tag: NTP_4_2_7P180~1^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50a79f3acd77bfe4681495af96a4d2e60a728f2d;p=thirdparty%2Fntp.git Update to libevent HEAD as of 20110604, e40bafe796a8e544e9e54e247cb3aa30c95e06b0 Snapshot of libevent 2.1, as of 2.0.12-stable release. bk: 4deb6714l4796Fn6rDPicqsu2TGkJQ --- diff --git a/sntp/libevent/ChangeLog b/sntp/libevent/ChangeLog index 9caf4064f..87f8db953 100644 --- a/sntp/libevent/ChangeLog +++ b/sntp/libevent/ChangeLog @@ -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: diff --git a/sntp/libevent/Makefile.am b/sntp/libevent/Makefile.am index 8511dc458..dae46c247 100644 --- a/sntp/libevent/Makefile.am +++ b/sntp/libevent/Makefile.am @@ -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 diff --git a/sntp/libevent/README b/sntp/libevent/README index 8044a98c4..bed2121a3 100644 --- a/sntp/libevent/README +++ b/sntp/libevent/README @@ -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 diff --git a/sntp/libevent/buffer.c b/sntp/libevent/buffer.c index 9d6ffc102..0a0be15b6 100644 --- a/sntp/libevent/buffer.c +++ b/sntp/libevent/buffer.c @@ -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 howfar from the position of pos within + * buf. 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; diff --git a/sntp/libevent/configure.in b/sntp/libevent/configure.in index 0aa1fb920..774d4afb7 100644 --- a/sntp/libevent/configure.in +++ b/sntp/libevent/configure.in @@ -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]) diff --git a/sntp/libevent/event.c b/sntp/libevent/event.c index 366d867de..62ec7f546 100644 --- a/sntp/libevent/event.c +++ b/sntp/libevent/event.c @@ -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 diff --git a/sntp/libevent/event_iocp.c b/sntp/libevent/event_iocp.c index fbeda703a..26ad64f26 100644 --- a/sntp/libevent/event_iocp.c +++ b/sntp/libevent/event_iocp.c @@ -25,6 +25,10 @@ */ #include "evconfig-private.h" +#ifndef _WIN32_WINNT +/* Minimum required for InitializeCriticalSectionAndSpinCount */ +#define _WIN32_WINNT 0x0403 +#endif #include #include #include diff --git a/sntp/libevent/evport.c b/sntp/libevent/evport.c index 1b78960f4..f7f559746 100644 --- a/sntp/libevent/evport.c +++ b/sntp/libevent/evport.c @@ -73,20 +73,8 @@ #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 @@ -94,7 +82,12 @@ */ 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); } diff --git a/sntp/libevent/evthread_win32.c b/sntp/libevent/evthread_win32.c index 7bb97bf96..2dcd70c20 100644 --- a/sntp/libevent/evthread_win32.c +++ b/sntp/libevent/evthread_win32.c @@ -27,6 +27,10 @@ #include "evconfig-private.h" #ifdef _WIN32 +#ifndef _WIN32_WINNT +/* Minimum required for InitializeCriticalSectionAndSpinCount */ +#define _WIN32_WINNT 0x0403 +#endif #include #define WIN32_LEAN_AND_MEAN #include diff --git a/sntp/libevent/http.c b/sntp/libevent/http.c index ac9289801..540c21d02 100644 --- a/sntp/libevent/http.c +++ b/sntp/libevent/http.c @@ -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); diff --git a/sntp/libevent/listener.c b/sntp/libevent/listener.c index aaceaae74..7f8033828 100644 --- a/sntp/libevent/listener.c +++ b/sntp/libevent/listener.c @@ -30,6 +30,10 @@ #include #ifdef _WIN32 +#ifndef _WIN32_WINNT +/* Minimum required for InitializeCriticalSectionAndSpinCount */ +#define _WIN32_WINNT 0x0403 +#endif #include #include #include diff --git a/sntp/libevent/select.c b/sntp/libevent/select.c index b2a373324..e418261df 100644 --- a/sntp/libevent/select.c +++ b/sntp/libevent/select.c @@ -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)) diff --git a/sntp/libevent/test/regress_http.c b/sntp/libevent/test/regress_http.c index b232469c8..48ed525e0 100644 --- a/sntp/libevent/test/regress_http.c +++ b/sntp/libevent/test/regress_http.c @@ -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); /* diff --git a/sntp/libevent/test/regress_ssl.c b/sntp/libevent/test/regress_ssl.c index c2f7a14da..6bac30e41 100644 --- a/sntp/libevent/test/regress_ssl.c +++ b/sntp/libevent/test/regress_ssl.c @@ -30,6 +30,7 @@ #endif #ifndef _WIN32 +#include #include #include #endif