From fdfabbec00b36bc6d5e69b5d8719e70d6f4e5b7b Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Sat, 2 Mar 2019 22:50:00 +0300 Subject: [PATCH] buffer: fix evbuffer_remove_buffer() with empty chain in front In case we have empty chain (chain that do not have any data, i.e. ->off == 0) at the beginning of the buffer, and no more full chains to move to the dst, we will skip moving of this empty chain, and hence last_with_datap will not be adjusted, and things will be broken after. Fix this by not relying on ->off, just count if we have something to move that's it. Test case from: https://github.com/envoyproxy/envoy/pull/6062 Fixes: #774 --- buffer.c | 2 +- test/regress_buffer.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/buffer.c b/buffer.c index f6ff8431..7a8c8b69 100644 --- a/buffer.c +++ b/buffer.c @@ -1299,7 +1299,7 @@ evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst, chain = chain->next; } - if (nread) { + if (chain != src->first) { /* we can remove the chain */ struct evbuffer_chain **chp; chp = evbuffer_free_trailing_empty_chains(dst); diff --git a/test/regress_buffer.c b/test/regress_buffer.c index a7f27416..67072ec8 100644 --- a/test/regress_buffer.c +++ b/test/regress_buffer.c @@ -423,6 +423,33 @@ test_evbuffer_remove_buffer_with_empty3(void *ptr) evbuffer_free(buf); } +static void +test_evbuffer_remove_buffer_with_empty_front(void *ptr) +{ + struct evbuffer *buf1 = NULL, *buf2 = NULL; + + buf1 = evbuffer_new(); + tt_assert(buf1); + + buf2 = evbuffer_new(); + tt_assert(buf2); + + tt_int_op(evbuffer_add_reference(buf1, "foo", 3, NULL, NULL), ==, 0); + tt_int_op(evbuffer_prepend(buf1, "", 0), ==, 0); + tt_int_op(evbuffer_remove_buffer(buf1, buf2, 1), ==, 1); + tt_int_op(evbuffer_add(buf1, "bar", 3), ==, 0); + tt_mem_op(evbuffer_pullup(buf1, -1), ==, "oobar", 5); + + evbuffer_validate(buf1); + evbuffer_validate(buf2); + + end: + if (buf1) + evbuffer_free(buf1); + if (buf2) + evbuffer_free(buf2); +} + static void test_evbuffer_add_buffer_with_empty(void *ptr) { @@ -2522,6 +2549,7 @@ struct testcase_t evbuffer_testcases[] = { { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL }, { "remove_buffer_with_empty2", test_evbuffer_remove_buffer_with_empty2, 0, NULL, NULL }, { "remove_buffer_with_empty3", test_evbuffer_remove_buffer_with_empty3, 0, NULL, NULL }, + { "remove_buffer_with_empty_front", test_evbuffer_remove_buffer_with_empty_front, 0, NULL, NULL }, { "add_buffer_with_empty", test_evbuffer_add_buffer_with_empty, 0, NULL, NULL }, { "add_buffer_with_empty2", test_evbuffer_add_buffer_with_empty2, 0, NULL, NULL }, { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL }, -- 2.50.1