mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-13 22:37:42 -04:00
fix a bug in which evbuffer_add_vfprintf would loop forever; avoid
fragmentation in evbuffer_expand by increasing the size of the last buffer in the chain; as a result with have to keep track of the previous_to_last chain; provide a evbuffer_validate() function in the regression test to make sure that all evbuffer are internally consistent. svn:r699
This commit is contained in:
parent
3ef1f50415
commit
193c06a7ed
109
buffer.c
109
buffer.c
@ -122,6 +122,37 @@ evbuffer_length(struct evbuffer *buffer)
|
|||||||
return (buffer->total_len);
|
return (buffer->total_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ZERO_CHAIN(dst) do { \
|
||||||
|
(dst)->first = NULL; \
|
||||||
|
(dst)->last = NULL; \
|
||||||
|
(dst)->previous_to_last = NULL; \
|
||||||
|
(dst)->total_len = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define COPY_CHAIN(dst, src) do { \
|
||||||
|
(dst)->first = (src)->first; \
|
||||||
|
(dst)->previous_to_last = (src)->previous_to_last; \
|
||||||
|
(dst)->last = (src)->last; \
|
||||||
|
(dst)->total_len = (src)->total_len; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define APPEND_CHAIN(dst, src) do { \
|
||||||
|
(dst)->last->next = (src)->first; \
|
||||||
|
(dst)->previous_to_last = (src)->previous_to_last ? \
|
||||||
|
(src)->previous_to_last : (dst)->last; \
|
||||||
|
(dst)->last = (src)->last; \
|
||||||
|
(dst)->total_len += (src)->total_len; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define PREPEND_CHAIN(dst, src) do { \
|
||||||
|
(src)->last->next = (dst)->first; \
|
||||||
|
(dst)->first = (src)->first; \
|
||||||
|
(dst)->total_len += (src)->total_len; \
|
||||||
|
if ((dst)->previous_to_last == NULL) \
|
||||||
|
(dst)->previous_to_last = (src)->last; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
||||||
{
|
{
|
||||||
@ -129,19 +160,13 @@ evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
|||||||
size_t in_total_len = inbuf->total_len;
|
size_t in_total_len = inbuf->total_len;
|
||||||
|
|
||||||
if (out_total_len == 0) {
|
if (out_total_len == 0) {
|
||||||
outbuf->first = inbuf->first;
|
COPY_CHAIN(outbuf, inbuf);
|
||||||
outbuf->last = inbuf->last;
|
|
||||||
outbuf->total_len = in_total_len;
|
|
||||||
} else {
|
} else {
|
||||||
outbuf->last->next = inbuf->first;
|
APPEND_CHAIN(outbuf, inbuf);
|
||||||
outbuf->last = inbuf->last;
|
|
||||||
outbuf->total_len += in_total_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove everything from inbuf */
|
/* remove everything from inbuf */
|
||||||
inbuf->first = NULL;
|
ZERO_CHAIN(inbuf);
|
||||||
inbuf->last = NULL;
|
|
||||||
inbuf->total_len = 0;
|
|
||||||
|
|
||||||
if (inbuf->cb != NULL && inbuf->total_len != in_total_len)
|
if (inbuf->cb != NULL && inbuf->total_len != in_total_len)
|
||||||
(*inbuf->cb)(inbuf, in_total_len, inbuf->total_len,
|
(*inbuf->cb)(inbuf, in_total_len, inbuf->total_len,
|
||||||
@ -163,19 +188,13 @@ evbuffer_prepend_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (out_total_len == 0) {
|
if (out_total_len == 0) {
|
||||||
outbuf->first = inbuf->first;
|
COPY_CHAIN(outbuf, inbuf);
|
||||||
outbuf->last = inbuf->last;
|
|
||||||
outbuf->total_len = in_total_len;
|
|
||||||
} else {
|
} else {
|
||||||
inbuf->last->next = outbuf->first;
|
PREPEND_CHAIN(outbuf, inbuf);
|
||||||
outbuf->first = inbuf->first;
|
|
||||||
outbuf->total_len += in_total_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove everything from inbuf */
|
/* remove everything from inbuf */
|
||||||
inbuf->first = NULL;
|
ZERO_CHAIN(inbuf);
|
||||||
inbuf->last = NULL;
|
|
||||||
inbuf->total_len = 0;
|
|
||||||
|
|
||||||
if (inbuf->cb != NULL && inbuf->total_len != in_total_len)
|
if (inbuf->cb != NULL && inbuf->total_len != in_total_len)
|
||||||
(*inbuf->cb)(inbuf, in_total_len, inbuf->total_len,
|
(*inbuf->cb)(inbuf, in_total_len, inbuf->total_len,
|
||||||
@ -201,8 +220,7 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
|
|||||||
event_free(chain);
|
event_free(chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->total_len = 0;
|
ZERO_CHAIN(buf);
|
||||||
buf->first = buf->last = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
buf->total_len -= len;
|
buf->total_len -= len;
|
||||||
|
|
||||||
@ -214,6 +232,8 @@ evbuffer_drain(struct evbuffer *buf, size_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf->first = chain;
|
buf->first = chain;
|
||||||
|
if (buf->first == buf->last)
|
||||||
|
buf->previous_to_last = NULL;
|
||||||
chain->misalign += len;
|
chain->misalign += len;
|
||||||
chain->off -= len;
|
chain->off -= len;
|
||||||
}
|
}
|
||||||
@ -254,6 +274,8 @@ evbuffer_remove(struct evbuffer *buf, void *data_out, size_t datlen)
|
|||||||
buf->first = chain;
|
buf->first = chain;
|
||||||
if (chain == NULL)
|
if (chain == NULL)
|
||||||
buf->last = NULL;
|
buf->last = NULL;
|
||||||
|
if (buf->first == buf->last)
|
||||||
|
buf->previous_to_last = NULL;
|
||||||
|
|
||||||
if (datlen) {
|
if (datlen) {
|
||||||
memcpy(data, chain->buffer + chain->misalign, datlen);
|
memcpy(data, chain->buffer + chain->misalign, datlen);
|
||||||
@ -276,7 +298,8 @@ int
|
|||||||
evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
|
evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
|
||||||
size_t datlen)
|
size_t datlen)
|
||||||
{
|
{
|
||||||
struct evbuffer_chain *chain = src->first, *previous = chain;
|
struct evbuffer_chain *chain = src->first;
|
||||||
|
struct evbuffer_chain *previous = chain, *previous_to_previous = NULL;
|
||||||
size_t nread = 0;
|
size_t nread = 0;
|
||||||
|
|
||||||
/* short-cut if there is no more data buffered */
|
/* short-cut if there is no more data buffered */
|
||||||
@ -293,6 +316,7 @@ evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
|
|||||||
while (chain->off <= datlen) {
|
while (chain->off <= datlen) {
|
||||||
nread += chain->off;
|
nread += chain->off;
|
||||||
datlen -= chain->off;
|
datlen -= chain->off;
|
||||||
|
previous_to_previous = previous;
|
||||||
previous = chain;
|
previous = chain;
|
||||||
chain = chain->next;
|
chain = chain->next;
|
||||||
}
|
}
|
||||||
@ -304,9 +328,12 @@ evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
|
|||||||
} else {
|
} else {
|
||||||
dst->last->next = src->first;
|
dst->last->next = src->first;
|
||||||
}
|
}
|
||||||
|
dst->previous_to_last = previous_to_previous;
|
||||||
dst->last = previous;
|
dst->last = previous;
|
||||||
previous->next = NULL;
|
previous->next = NULL;
|
||||||
src->first = chain;
|
src->first = chain;
|
||||||
|
if (src->first == src->last)
|
||||||
|
src->previous_to_last = NULL;
|
||||||
|
|
||||||
dst->total_len += nread;
|
dst->total_len += nread;
|
||||||
}
|
}
|
||||||
@ -383,8 +410,12 @@ evbuffer_pullup(struct evbuffer *buf, int size)
|
|||||||
memcpy(buffer, chain->buffer + chain->misalign, size);
|
memcpy(buffer, chain->buffer + chain->misalign, size);
|
||||||
chain->misalign += size;
|
chain->misalign += size;
|
||||||
chain->off -= size;
|
chain->off -= size;
|
||||||
|
if (chain == buf->last)
|
||||||
|
buf->previous_to_last = tmp;
|
||||||
} else {
|
} else {
|
||||||
buf->last = tmp;
|
buf->last = tmp;
|
||||||
|
/* the last is already the first, so we have no previous */
|
||||||
|
buf->previous_to_last = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp->next = chain;
|
tmp->next = chain;
|
||||||
@ -605,6 +636,7 @@ evbuffer_add(struct evbuffer *buf, const void *data_in, size_t datlen)
|
|||||||
if (chain->next == NULL)
|
if (chain->next == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
buf->last = chain->next;
|
buf->last = chain->next;
|
||||||
|
buf->previous_to_last = chain;
|
||||||
buf->total_len += datlen;
|
buf->total_len += datlen;
|
||||||
|
|
||||||
memcpy(chain->buffer + chain->misalign + chain->off,
|
memcpy(chain->buffer + chain->misalign + chain->off,
|
||||||
@ -646,13 +678,15 @@ evbuffer_prepend(struct evbuffer *buf, const void *data, size_t datlen)
|
|||||||
chain->misalign -= datlen;
|
chain->misalign -= datlen;
|
||||||
} else {
|
} else {
|
||||||
struct evbuffer_chain *tmp;
|
struct evbuffer_chain *tmp;
|
||||||
/* XXX we should copy as much of the data into chain as possible
|
/* XXX we should copy as much of the data into chain
|
||||||
* before we put any into tmp. */
|
* as possible before we put any into tmp. */
|
||||||
|
|
||||||
/* we need to add another chain */
|
/* we need to add another chain */
|
||||||
if ((tmp = evbuffer_chain_new(datlen)) == NULL)
|
if ((tmp = evbuffer_chain_new(datlen)) == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
buf->first = tmp;
|
buf->first = tmp;
|
||||||
|
if (buf->previous_to_last == NULL)
|
||||||
|
buf->previous_to_last = tmp;
|
||||||
tmp->next = chain;
|
tmp->next = chain;
|
||||||
|
|
||||||
tmp->off = datlen;
|
tmp->off = datlen;
|
||||||
@ -691,6 +725,7 @@ evbuffer_expand(struct evbuffer *buf, size_t datlen)
|
|||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
buf->first = buf->last = chain;
|
buf->first = buf->last = chain;
|
||||||
|
buf->previous_to_last = NULL;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -700,25 +735,34 @@ evbuffer_expand(struct evbuffer *buf, size_t datlen)
|
|||||||
if (chain->buffer_len >= need)
|
if (chain->buffer_len >= need)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/* If the misalignment plus the remaining space fulfils our data needs, we
|
/* If the misalignment plus the remaining space fulfils our
|
||||||
* just force an alignment to happen. Afterwards, we have enough space.
|
* data needs, we just force an alignment to happen.
|
||||||
|
* Afterwards, we have enough space.
|
||||||
*/
|
*/
|
||||||
if (chain->buffer_len - chain->off >= datlen) {
|
if (chain->buffer_len - chain->off >= datlen) {
|
||||||
evbuffer_chain_align(chain);
|
evbuffer_chain_align(chain);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* avoid a memcpy if we can just append a new chain */
|
/* figure out how much space we need */
|
||||||
/* XXX in practice, does this result in lots of leftover space? */
|
length = chain->buffer_len - chain->misalign + datlen;
|
||||||
length = chain->buffer_len << 1;
|
|
||||||
if (length < datlen)
|
|
||||||
length = datlen;
|
|
||||||
tmp = evbuffer_chain_new(length);
|
tmp = evbuffer_chain_new(length);
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
return (-1);
|
return (-1);
|
||||||
chain->next = tmp;
|
/* copy the data over that we had so far */
|
||||||
|
tmp->off = chain->off;
|
||||||
|
tmp->misalign = 0;
|
||||||
|
memcpy(tmp->buffer, chain->buffer + chain->misalign, chain->off);
|
||||||
|
|
||||||
|
/* fix up the chain */
|
||||||
|
if (buf->first == chain)
|
||||||
|
buf->first = tmp;
|
||||||
|
if (buf->previous_to_last)
|
||||||
|
buf->previous_to_last->next = tmp;
|
||||||
buf->last = tmp;
|
buf->last = tmp;
|
||||||
|
|
||||||
|
event_free(chain);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,7 +895,6 @@ evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
|
|||||||
int
|
int
|
||||||
evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
|
evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
struct evbuffer_chain *chain;
|
|
||||||
char *buffer;
|
char *buffer;
|
||||||
size_t space;
|
size_t space;
|
||||||
size_t old_len = buf->total_len;
|
size_t old_len = buf->total_len;
|
||||||
@ -862,8 +905,8 @@ evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
|
|||||||
if (evbuffer_expand(buf, 64) == -1)
|
if (evbuffer_expand(buf, 64) == -1)
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
chain = buf->last;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
struct evbuffer_chain *chain = buf->last;
|
||||||
size_t used = chain->misalign + chain->off;
|
size_t used = chain->misalign + chain->off;
|
||||||
buffer = (char *)chain->buffer + chain->misalign + chain->off;
|
buffer = (char *)chain->buffer + chain->misalign + chain->off;
|
||||||
assert(chain->buffer_len >= used);
|
assert(chain->buffer_len >= used);
|
||||||
|
@ -45,6 +45,7 @@ struct evbuffer_chain;
|
|||||||
struct evbuffer {
|
struct evbuffer {
|
||||||
struct evbuffer_chain *first;
|
struct evbuffer_chain *first;
|
||||||
struct evbuffer_chain *last;
|
struct evbuffer_chain *last;
|
||||||
|
struct evbuffer_chain *previous_to_last;
|
||||||
|
|
||||||
size_t total_len; /* total length of all buffers */
|
size_t total_len; /* total length of all buffers */
|
||||||
|
|
||||||
|
135
test/regress.c
135
test/regress.c
@ -53,10 +53,12 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "evutil.h"
|
#include "evutil.h"
|
||||||
#include "event-internal.h"
|
#include "event-internal.h"
|
||||||
|
#include "evbuffer-internal.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#include "regress.h"
|
#include "regress.h"
|
||||||
@ -890,6 +892,38 @@ test_nonpersist_readd(void)
|
|||||||
cleanup_test();
|
cleanup_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* validates that an evbuffer is good */
|
||||||
|
static void
|
||||||
|
evbuffer_validate(struct evbuffer *buf)
|
||||||
|
{
|
||||||
|
struct evbuffer_chain *chain, *previous = NULL;
|
||||||
|
size_t sum = 0;
|
||||||
|
|
||||||
|
if (buf->first == NULL) {
|
||||||
|
assert(buf->last == NULL);
|
||||||
|
assert(buf->previous_to_last == NULL);
|
||||||
|
assert(buf->total_len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf->previous_to_last == NULL) {
|
||||||
|
assert(buf->first == buf->last);
|
||||||
|
}
|
||||||
|
|
||||||
|
chain = buf->first;
|
||||||
|
while (chain != NULL) {
|
||||||
|
sum += chain->off;
|
||||||
|
if (chain->next == NULL) {
|
||||||
|
assert(buf->previous_to_last == previous);
|
||||||
|
assert(buf->last == chain);
|
||||||
|
}
|
||||||
|
assert(chain->buffer_len >= chain->misalign + chain->off);
|
||||||
|
previous = chain;
|
||||||
|
chain = chain->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sum == buf->total_len);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_evbuffer(void)
|
test_evbuffer(void)
|
||||||
{
|
{
|
||||||
@ -900,19 +934,24 @@ test_evbuffer(void)
|
|||||||
int i;
|
int i;
|
||||||
setup_test("Testing Evbuffer: ");
|
setup_test("Testing Evbuffer: ");
|
||||||
|
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add_printf(evb, "%s/%d", "hello", 1);
|
evbuffer_add_printf(evb, "%s/%d", "hello", 1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
if (EVBUFFER_LENGTH(evb) != 7 ||
|
if (EVBUFFER_LENGTH(evb) != 7 ||
|
||||||
strcmp((char*)EVBUFFER_DATA(evb), "hello/1") != 0)
|
strcmp((char*)EVBUFFER_DATA(evb), "hello/1") != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
evbuffer_drain(evb, strlen("hello/"));
|
evbuffer_drain(evb, strlen("hello/"));
|
||||||
|
evbuffer_validate(evb);
|
||||||
if (EVBUFFER_LENGTH(evb) != 1 ||
|
if (EVBUFFER_LENGTH(evb) != 1 ||
|
||||||
strcmp((char*)EVBUFFER_DATA(evb), "1") != 0)
|
strcmp((char*)EVBUFFER_DATA(evb), "1") != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
evbuffer_add_printf(evb_two, "%s", "/hello");
|
evbuffer_add_printf(evb_two, "%s", "/hello");
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add_buffer(evb, evb_two);
|
evbuffer_add_buffer(evb, evb_two);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
if (EVBUFFER_LENGTH(evb_two) != 0 ||
|
if (EVBUFFER_LENGTH(evb_two) != 0 ||
|
||||||
EVBUFFER_LENGTH(evb) != 7 ||
|
EVBUFFER_LENGTH(evb) != 7 ||
|
||||||
@ -921,6 +960,7 @@ test_evbuffer(void)
|
|||||||
|
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
evbuffer_add(evb, buffer, sizeof(buffer));
|
evbuffer_add(evb, buffer, sizeof(buffer));
|
||||||
|
evbuffer_validate(evb);
|
||||||
if (EVBUFFER_LENGTH(evb) != 7 + 512)
|
if (EVBUFFER_LENGTH(evb) != 7 + 512)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -931,20 +971,29 @@ test_evbuffer(void)
|
|||||||
goto out;
|
goto out;
|
||||||
if (memcmp(tmp + 7, buffer, sizeof(buffer)) != 0)
|
if (memcmp(tmp + 7, buffer, sizeof(buffer)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
evbuffer_prepend(evb, "something", 9);
|
evbuffer_prepend(evb, "something", 9);
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_prepend(evb, "else", 4);
|
evbuffer_prepend(evb, "else", 4);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
|
tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
|
||||||
if (strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7) != 0)
|
if (strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
evbuffer_drain(evb, -1);
|
evbuffer_drain(evb, -1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_drain(evb_two, -1);
|
evbuffer_drain(evb_two, -1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
evbuffer_add(evb_two, buffer, sizeof(buffer));
|
evbuffer_add(evb_two, buffer, sizeof(buffer));
|
||||||
|
evbuffer_validate(evb_two);
|
||||||
evbuffer_add_buffer(evb, evb_two);
|
evbuffer_add_buffer(evb, evb_two);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
evbuffer_validate(evb_two);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EVBUFFER_LENGTH(evb_two) != 0 ||
|
if (EVBUFFER_LENGTH(evb_two) != 0 ||
|
||||||
@ -957,12 +1006,14 @@ test_evbuffer(void)
|
|||||||
if (EVBUFFER_LENGTH(evb_two) != sz_tmp ||
|
if (EVBUFFER_LENGTH(evb_two) != sz_tmp ||
|
||||||
EVBUFFER_LENGTH(evb) != sizeof(buffer) / 2)
|
EVBUFFER_LENGTH(evb) != sizeof(buffer) / 2)
|
||||||
goto out;
|
goto out;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
if (memcmp(evbuffer_pullup(
|
if (memcmp(evbuffer_pullup(
|
||||||
evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
|
evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
|
||||||
memcmp(evbuffer_pullup(
|
memcmp(evbuffer_pullup(
|
||||||
evb_two, -1), buffer, sizeof(buffer) != 0))
|
evb_two, -1), buffer, sizeof(buffer) != 0))
|
||||||
goto out;
|
goto out;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
test_ok = 1;
|
test_ok = 1;
|
||||||
|
|
||||||
@ -986,123 +1037,169 @@ test_evbuffer_readln(void)
|
|||||||
/* Test EOL_ANY. */
|
/* Test EOL_ANY. */
|
||||||
s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
|
s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
|
||||||
evbuffer_add(evb, s, strlen(s)+2);
|
evbuffer_add(evb, s, strlen(s)+2);
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "complex silly newline"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "complex silly newline"))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
||||||
if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
|
if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
|
||||||
goto done;
|
goto done;
|
||||||
if (EVBUFFER_LENGTH(evb) != 0)
|
if (EVBUFFER_LENGTH(evb) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
s = "\nno newline";
|
s = "\nno newline";
|
||||||
evbuffer_add(evb, s, strlen(s));
|
evbuffer_add(evb, s, strlen(s));
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
||||||
if (!cp || sz || strcmp(cp, ""))
|
if (!cp || sz || strcmp(cp, ""))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
|
||||||
if (cp)
|
if (cp)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_drain(evb, EVBUFFER_LENGTH(evb));
|
evbuffer_drain(evb, EVBUFFER_LENGTH(evb));
|
||||||
if (EVBUFFER_LENGTH(evb) != 0)
|
if (EVBUFFER_LENGTH(evb) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
/* Test EOL_CRLF */
|
/* Test EOL_CRLF */
|
||||||
s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
|
s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
|
||||||
evbuffer_add(evb, s, strlen(s));
|
evbuffer_add(evb, s, strlen(s));
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "Line with\rin the middle"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "Line with\rin the middle"))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "Line with good crlf"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "Line with good crlf"))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "final"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "final"))
|
||||||
goto done;
|
goto done;
|
||||||
s = "x";
|
s = "x";
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add(evb, s, 1);
|
evbuffer_add(evb, s, 1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
free(cp);
|
free(cp);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
|
||||||
if (cp)
|
if (cp)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
/* Test CRLF_STRICT */
|
/* Test CRLF_STRICT */
|
||||||
s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
|
s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
|
||||||
evbuffer_add(evb, s, strlen(s));
|
evbuffer_add(evb, s, strlen(s));
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (!cp || sz != strlen(cp) ||
|
if (!cp || sz != strlen(cp) ||
|
||||||
strcmp(cp, "x and a bad crlf\nand a good one"))
|
strcmp(cp, "x and a bad crlf\nand a good one"))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (cp)
|
if (cp)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add(evb, "\n", 1);
|
evbuffer_add(evb, "\n", 1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "More"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "More"))
|
||||||
goto done;
|
goto done;
|
||||||
if (EVBUFFER_LENGTH(evb) != 0)
|
if (EVBUFFER_LENGTH(evb) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
/* Test LF */
|
/* Test LF */
|
||||||
s = "An\rand a nl\n\nText";
|
s = "An\rand a nl\n\nText";
|
||||||
evbuffer_add(evb, s, strlen(s));
|
evbuffer_add(evb, s, strlen(s));
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "An\rand a nl"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "An\rand a nl"))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
||||||
if (cp)
|
if (cp)
|
||||||
goto done;
|
goto done;
|
||||||
evbuffer_add(evb, "\n", 1);
|
evbuffer_add(evb, "\n", 1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "Text"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "Text"))
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
/* Test CRLF_STRICT - across boundaries*/
|
/* Test CRLF_STRICT - across boundaries*/
|
||||||
s = " and a bad crlf\nand a good one\r";
|
s = " and a bad crlf\nand a good one\r";
|
||||||
evbuffer_add(evb_tmp, s, strlen(s));
|
evbuffer_add(evb_tmp, s, strlen(s));
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add_buffer(evb, evb_tmp);
|
evbuffer_add_buffer(evb, evb_tmp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
s = "\n\r";
|
s = "\n\r";
|
||||||
evbuffer_add(evb_tmp, s, strlen(s));
|
evbuffer_add(evb_tmp, s, strlen(s));
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add_buffer(evb, evb_tmp);
|
evbuffer_add_buffer(evb, evb_tmp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
s = "\nMore\r";
|
s = "\nMore\r";
|
||||||
evbuffer_add(evb_tmp, s, strlen(s));
|
evbuffer_add(evb_tmp, s, strlen(s));
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add_buffer(evb, evb_tmp);
|
evbuffer_add_buffer(evb, evb_tmp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (!cp || sz != strlen(cp) ||
|
if (!cp || sz != strlen(cp) ||
|
||||||
strcmp(cp, " and a bad crlf\nand a good one"))
|
strcmp(cp, " and a bad crlf\nand a good one"))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
if (!cp || sz != strlen(cp) || strcmp(cp, ""))
|
||||||
goto done;
|
goto done;
|
||||||
free(cp);
|
free(cp);
|
||||||
|
evbuffer_validate(evb);
|
||||||
|
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (cp)
|
if (cp)
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
evbuffer_add(evb, "\n", 1);
|
evbuffer_add(evb, "\n", 1);
|
||||||
|
evbuffer_validate(evb);
|
||||||
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
|
||||||
if (!cp || sz != strlen(cp) || strcmp(cp, "More"))
|
if (!cp || sz != strlen(cp) || strcmp(cp, "More"))
|
||||||
goto done;
|
goto done;
|
||||||
|
evbuffer_validate(evb);
|
||||||
if (EVBUFFER_LENGTH(evb) != 0)
|
if (EVBUFFER_LENGTH(evb) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
@ -1115,6 +1212,36 @@ test_evbuffer_readln(void)
|
|||||||
cleanup_test();
|
cleanup_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_evbuffer_iterative(void)
|
||||||
|
{
|
||||||
|
struct evbuffer *buf = evbuffer_new();
|
||||||
|
const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
|
||||||
|
int i, j, sum;
|
||||||
|
|
||||||
|
setup_test("Testing evbuffer() iterative: ");
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
for (i = 0; i < 1000; ++i) {
|
||||||
|
for (j = 1; j < strlen(abc); ++j) {
|
||||||
|
char format[32];
|
||||||
|
|
||||||
|
snprintf(format, sizeof(format), "%%%d.%ds", j, j);
|
||||||
|
evbuffer_add_printf(buf, format, abc);
|
||||||
|
evbuffer_validate(buf);
|
||||||
|
|
||||||
|
sum += j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sum == EVBUFFER_LENGTH(buf))
|
||||||
|
test_ok = 1;
|
||||||
|
|
||||||
|
evbuffer_free(buf);
|
||||||
|
|
||||||
|
cleanup_test();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_evbuffer_find(void)
|
test_evbuffer_find(void)
|
||||||
{
|
{
|
||||||
@ -1129,8 +1256,11 @@ test_evbuffer_find(void)
|
|||||||
/* make sure evbuffer_find doesn't match past the end of the buffer */
|
/* make sure evbuffer_find doesn't match past the end of the buffer */
|
||||||
fprintf(stdout, "Testing evbuffer_find 1: ");
|
fprintf(stdout, "Testing evbuffer_find 1: ");
|
||||||
evbuffer_add(buf, (u_char*)test1, strlen(test1));
|
evbuffer_add(buf, (u_char*)test1, strlen(test1));
|
||||||
|
evbuffer_validate(buf);
|
||||||
evbuffer_drain(buf, strlen(test1));
|
evbuffer_drain(buf, strlen(test1));
|
||||||
|
evbuffer_validate(buf);
|
||||||
evbuffer_add(buf, (u_char*)test2, strlen(test2));
|
evbuffer_add(buf, (u_char*)test2, strlen(test2));
|
||||||
|
evbuffer_validate(buf);
|
||||||
p = evbuffer_find(buf, (u_char*)"\r\n", 2);
|
p = evbuffer_find(buf, (u_char*)"\r\n", 2);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
fprintf(stdout, "OK\n");
|
fprintf(stdout, "OK\n");
|
||||||
@ -1145,10 +1275,12 @@ test_evbuffer_find(void)
|
|||||||
*/
|
*/
|
||||||
fprintf(stdout, "Testing evbuffer_find 2: ");
|
fprintf(stdout, "Testing evbuffer_find 2: ");
|
||||||
evbuffer_drain(buf, strlen(test2));
|
evbuffer_drain(buf, strlen(test2));
|
||||||
|
evbuffer_validate(buf);
|
||||||
for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
|
for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
|
||||||
test3[i] = 'a';
|
test3[i] = 'a';
|
||||||
test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
|
test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
|
||||||
evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
|
evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
|
||||||
|
evbuffer_validate(buf);
|
||||||
p = evbuffer_find(buf, (u_char *)"xy", 2);
|
p = evbuffer_find(buf, (u_char *)"xy", 2);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
printf("OK\n");
|
printf("OK\n");
|
||||||
@ -1718,6 +1850,7 @@ main (int argc, char **argv)
|
|||||||
test_priorities(3);
|
test_priorities(3);
|
||||||
|
|
||||||
test_evbuffer();
|
test_evbuffer();
|
||||||
|
test_evbuffer_iterative();
|
||||||
test_evbuffer_readln();
|
test_evbuffer_readln();
|
||||||
test_evbuffer_find();
|
test_evbuffer_find();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user