From 8e8d94a3e08d4cfa9cb817ae36fd4181edea84d2 Mon Sep 17 00:00:00 2001 From: Niels Provos Date: Thu, 24 Sep 2009 22:18:19 +0000 Subject: [PATCH] Do not drop data from evbuffer when out of memory; reported by Jacek Masiulaniec svn:r1436 --- ChangeLog | 1 + buffer.c | 1 - test/regress_buffer.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d005b214..ff45f1a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ Changes in 2.0.3-alpha: o Do not allocate the maximum event queue for the epoll backend at startup. Instead, start out accepting 32 events at a time, and double the queue's size when it seems that the OS is generating events faster than we're requesting them. Saves up to 374K per epoll-based event_base. Resolves bug 2839240. o Treat an event with a negative fd as valid but untriggerable by Libevent. This is useful for applications that want to manually activate events. o Fix compilation on Android, which forgot to define fd_mask in its sys/select.h + o Do not drop data from evbuffer when out of memory; reported by Jacek Masiulaniec Changes in 2.0.2-alpha: diff --git a/buffer.c b/buffer.c index 370823e2..979bc7d0 100644 --- a/buffer.c +++ b/buffer.c @@ -1172,7 +1172,6 @@ evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, if ((line = mm_malloc(n_to_copy+1)) == NULL) { event_warn("%s: out of memory\n", __func__); - evbuffer_drain(buffer, n_to_copy + extra_drain); goto done; } diff --git a/test/regress_buffer.c b/test/regress_buffer.c index a6031a02..ff0b9722 100644 --- a/test/regress_buffer.c +++ b/test/regress_buffer.c @@ -403,6 +403,12 @@ test_evbuffer_add_file(void *ptr) } #endif +static void * +failing_malloc(size_t how_much) +{ + return NULL; +} + static void test_evbuffer_readln(void *ptr) { @@ -586,6 +592,31 @@ test_evbuffer_readln(void *ptr) evbuffer_validate(evb); tt_assert(evbuffer_get_length(evb) == 0); + /* Test memory problem*/ + s = "one line\ntwo line\nblue line"; + evbuffer_add(evb_tmp, s, strlen(s)); + evbuffer_validate(evb); + evbuffer_add_buffer(evb, evb_tmp); + evbuffer_validate(evb); + + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq("one line"); + free(cp); cp = NULL; + evbuffer_validate(evb); + + /* the next call to readline should fail */ + event_set_mem_functions(failing_malloc, realloc, free); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_assert(cp == NULL); + evbuffer_validate(evb); + + /* now we should get the next line back */ + event_set_mem_functions(malloc, realloc, free); + cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); + tt_line_eq("two line"); + free(cp); cp = NULL; + evbuffer_validate(evb); + test_ok = 1; end: evbuffer_free(evb);