Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 57 additions & 10 deletions app/src/main/cpp/libevent/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,18 @@ evbuffer_chain_new(size_t size)

size += EVBUFFER_CHAIN_SIZE;

if (size > EVBUFFER_CHAIN_MAX - EVBUFFER_CHAIN_SIZE)
return (NULL);

/* get the next largest memory that can hold the buffer */
to_alloc = MIN_BUFFER_SIZE;
while (to_alloc < size)
to_alloc <<= 1;
if (size < EVBUFFER_CHAIN_MAX / 2) {
to_alloc = MIN_BUFFER_SIZE;
while (to_alloc < size) {
to_alloc <<= 1;
}
} else {
to_alloc = size;
}

/* we get everything in one chunk */
if ((chain = mm_malloc(to_alloc)) == NULL)
Expand Down Expand Up @@ -1003,6 +1011,7 @@ evbuffer_drain(struct evbuffer *buf, size_t len)

buf->first = chain;
if (chain) {
EVUTIL_ASSERT(remaining <= chain->off);
chain->misalign += remaining;
chain->off -= remaining;
}
Expand Down Expand Up @@ -1069,6 +1078,7 @@ evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen)

if (datlen) {
EVUTIL_ASSERT(chain);
EVUTIL_ASSERT(datlen <= chain->off);
memcpy(data, chain->buffer + chain->misalign, datlen);
}

Expand Down Expand Up @@ -1544,6 +1554,10 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
if (buf->freeze_end) {
goto done;
}
/* Prevent buf->total_len overflow */
if (datlen > EV_SIZE_MAX - buf->total_len) {
goto done;
}

chain = buf->last;

Expand All @@ -1557,7 +1571,10 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
}

if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
remain = (size_t)(chain->buffer_len - chain->misalign - chain->off);
/* Always true for mutable buffers */
EVUTIL_ASSERT(chain->misalign >= 0 &&
(ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX);
remain = chain->buffer_len - (size_t)chain->misalign - chain->off;
if (remain >= datlen) {
/* there's enough space to hold all the data in the
* current last chain */
Expand Down Expand Up @@ -1628,6 +1645,9 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
if (buf->freeze_start) {
goto done;
}
if (datlen > EV_SIZE_MAX - buf->total_len) {
goto done;
}

chain = buf->first;

Expand All @@ -1640,6 +1660,10 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)

/* we cannot touch immutable buffers */
if ((chain->flags & EVBUFFER_IMMUTABLE) == 0) {
/* Always true for mutable buffers */
EVUTIL_ASSERT(chain->misalign >= 0 &&
(ev_uint64_t)chain->misalign <= EVBUFFER_CHAIN_MAX);

/* If this chain is empty, we can treat it as
* 'empty at the beginning' rather than 'empty at the end' */
if (chain->off == 0)
Expand Down Expand Up @@ -1677,6 +1701,7 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
tmp->next = chain;

tmp->off = datlen;
EVUTIL_ASSERT(datlen <= tmp->buffer_len);
tmp->misalign = tmp->buffer_len - datlen;

memcpy(tmp->buffer + tmp->misalign, data, datlen);
Expand Down Expand Up @@ -1775,7 +1800,8 @@ evbuffer_expand_singlechain(struct evbuffer *buf, size_t datlen)

/* Would expanding this chunk be affordable and worthwhile? */
if (CHAIN_SPACE_LEN(chain) < chain->buffer_len / 8 ||
chain->off > MAX_TO_COPY_IN_EXPAND) {
chain->off > MAX_TO_COPY_IN_EXPAND ||
datlen >= (EVBUFFER_CHAIN_MAX - chain->off)) {
/* It's not worth resizing this chain. Can the next one be
* used? */
if (chain->next && CHAIN_SPACE_LEN(chain->next) >= datlen) {
Expand Down Expand Up @@ -1913,6 +1939,7 @@ _evbuffer_expand_fast(struct evbuffer *buf, size_t datlen, int n)
EVUTIL_ASSERT(chain->off == 0);
evbuffer_chain_free(chain);
}
EVUTIL_ASSERT(datlen >= avail);
tmp = evbuffer_chain_new(datlen - avail);
if (tmp == NULL) {
if (rmv_all) {
Expand Down Expand Up @@ -2154,8 +2181,14 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch)
#ifdef USE_IOVEC_IMPL
remaining = n;
for (i=0; i < nvecs; ++i) {
ev_ssize_t space = (ev_ssize_t) CHAIN_SPACE_LEN(*chainp);
if (space < remaining) {
/* can't overflow, since only mutable chains have
* huge misaligns. */
size_t space = (size_t) CHAIN_SPACE_LEN(*chainp);
/* XXXX This is a kludge that can waste space in perverse
* situations. */
if (space > EVBUFFER_CHAIN_MAX)
space = EVBUFFER_CHAIN_MAX;
if ((ev_ssize_t)space < remaining) {
(*chainp)->off += space;
remaining -= (int)space;
} else {
Expand Down Expand Up @@ -2426,12 +2459,16 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
case EVBUFFER_PTR_ADD:
/* this avoids iterating over all previous chains if
we just want to advance the position */
if (pos->pos < 0 || EV_SIZE_MAX - position < (size_t)pos->pos) {
EVBUFFER_UNLOCK(buf);
return -1;
}
chain = pos->_internal.chain;
pos->pos += position;
position = pos->_internal.pos_in_chain;
break;
}

EVUTIL_ASSERT(EV_SIZE_MAX - left >= position);
while (chain && position + left >= chain->off) {
left -= chain->off - position;
chain = chain->next;
Expand Down Expand Up @@ -2464,7 +2501,9 @@ evbuffer_ptr_memcmp(const struct evbuffer *buf, const struct evbuffer_ptr *pos,

ASSERT_EVBUFFER_LOCKED(buf);

if (pos->pos + len > buf->total_len)
if (pos->pos < 0 ||
EV_SIZE_MAX - len < (size_t)pos->pos ||
pos->pos + len > buf->total_len)
return -1;

chain = pos->_internal.chain;
Expand Down Expand Up @@ -2652,6 +2691,9 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)

if (sz < 0)
goto done;
if (INT_MAX >= EVBUFFER_CHAIN_MAX &&
(size_t)sz >= EVBUFFER_CHAIN_MAX)
goto done;
if ((size_t)sz < space) {
chain->off += sz;
buf->total_len += sz;
Expand Down Expand Up @@ -2744,6 +2786,10 @@ evbuffer_add_file(struct evbuffer *outbuf, int fd,
int sendfile_okay = 1;
#endif
int ok = 1;
if (offset < 0 || length < 0 ||
((ev_uint64_t)length > EVBUFFER_CHAIN_MAX) ||
(ev_uint64_t)offset > (ev_uint64_t)(EVBUFFER_CHAIN_MAX - length))
return (-1);

#if defined(USE_SENDFILE)
if (use_sendfile) {
Expand Down Expand Up @@ -2850,7 +2896,8 @@ evbuffer_add_file(struct evbuffer *outbuf, int fd,
* can abort without side effects if the read fails.
*/
while (length) {
read = evbuffer_readfile(tmp, fd, (ev_ssize_t)length);
ev_ssize_t to_read = length > EV_SSIZE_MAX ? EV_SSIZE_MAX : (ev_ssize_t)length;
read = evbuffer_readfile(tmp, fd, to_read);
if (read == -1) {
evbuffer_free(tmp);
return (-1);
Expand Down
14 changes: 13 additions & 1 deletion app/src/main/cpp/libevent/evbuffer-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ struct evbuffer {
struct bufferevent *parent;
};

#if _EVENT_SIZEOF_OFF_T < _EVENT_SIZEOF_SIZE_T
typedef ev_ssize_t ev_misalign_t;
#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX)
#else
typedef ev_off_t ev_misalign_t;
#if _EVENT_SIZEOF_OFF_T > _EVENT_SIZEOF_SIZE_T
#define EVBUFFER_CHAIN_MAX EV_SIZE_MAX
#else
#define EVBUFFER_CHAIN_MAX ((size_t)EV_SSIZE_MAX)
#endif
#endif

/** A single item in an evbuffer. */
struct evbuffer_chain {
/** points to next buffer in the chain */
Expand All @@ -163,7 +175,7 @@ struct evbuffer_chain {

/** unused space at the beginning of buffer or an offset into a
* file for sendfile buffers. */
ev_off_t misalign;
ev_misalign_t misalign;

/** Offset into buffer + misalign at which to start writing.
* In other words, the total number of bytes actually stored
Expand Down