From 4ccf511f086f63274a2a5f268a0c3bdf84db2f86 Mon Sep 17 00:00:00 2001
From: Nir Soffer <nirsof@gmail.com>
Date: Tue, 7 Jun 2011 16:22:01 +0300
Subject: [PATCH 3/3] Allow evbuffer_ptr to point after the buffer contents

This allows calling evbuffer_search_range with an end position, without
checking the buffer length.

Signed-off-by: Nir Soffer <nirsof@gmail.com>
---
 buffer.c              |    8 +++++++-
 test/regress_buffer.c |   36 ++++++++++++++++++++++++++++++------
 2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/buffer.c b/buffer.c
index 98de504..d82a5f4 100644
--- a/buffer.c
+++ b/buffer.c
@@ -2309,6 +2309,7 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
 {
 	size_t left = position;
 	struct evbuffer_chain *chain = NULL;
+	int result = 0;
 
 	EVBUFFER_LOCK(buf);
 
@@ -2335,14 +2336,19 @@ evbuffer_ptr_set(struct evbuffer *buf, struct evbuffer_ptr *pos,
 	if (chain) {
 		pos->_internal.chain = chain;
 		pos->_internal.pos_in_chain = position + left;
+	} else if (left >= 0 && buf->last) {
+		/* pos->pos points after the end of the buffer */
+		pos->_internal.chain = buf->last;
+		pos->_internal.pos_in_chain = buf->last->off;
 	} else {
 		pos->_internal.chain = NULL;
 		pos->pos = -1;
+		result = -1;
 	}
 
 	EVBUFFER_UNLOCK(buf);
 
-	return chain != NULL ? 0 : -1;
+	return result;
 }
 
 /**
diff --git a/test/regress_buffer.c b/test/regress_buffer.c
index ddb0ee7..7f0a369 100644
--- a/test/regress_buffer.c
+++ b/test/regress_buffer.c
@@ -1210,11 +1210,12 @@ test_evbuffer_ptr_set(void *ptr)
 
 	tt_int_op(evbuffer_get_length(buf), ==, 12000);
 
-	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
-	tt_assert(pos.pos == -1);
+	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == 0);
+	tt_assert(pos.pos == 13000);
 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
 	tt_assert(pos.pos == 0);
-	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
+	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == 0);
+	tt_assert(pos.pos == 13000);
 
 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
 	tt_assert(pos.pos == 0);
@@ -1222,8 +1223,12 @@ test_evbuffer_ptr_set(void *ptr)
 	tt_assert(pos.pos == 10000);
 	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
 	tt_assert(pos.pos == 11000);
-	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
-	tt_assert(pos.pos == -1);
+	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
+	tt_assert(pos.pos == 12000);
+	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
+	tt_assert(pos.pos == 13000);
+	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
+	tt_assert(pos.pos == 14000);
 
 end:
 	if (buf)
@@ -1280,10 +1285,29 @@ test_evbuffer_search(void *ptr)
 	pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
 	tt_int_op(pos.pos, ==, -1);
     
-	/* Point "end" after the last byte in the buffer */
+	/* Search when range is exactly the whole buffer - end points to the byte
+	 * after the last byte. */
 	tt_int_op(evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET), ==, 0);
 	pos = evbuffer_search_range(buf, "attack", 6, NULL, &end);
 	tt_int_op(pos.pos, ==, 11);
+	pos = evbuffer_search_range(buf, "attacker", 8, NULL, &end);
+	tt_int_op(pos.pos, ==, -1);
+
+	/* Search when range is bigger then the buffer */
+	tt_int_op(evbuffer_ptr_set(buf, &end, 18, EVBUFFER_PTR_SET), ==, 0);
+	pos = evbuffer_search_range(buf, "attack", 6, NULL, &end);
+	tt_int_op(pos.pos, ==, 11);
+	pos = evbuffer_search_range(buf, "attacker", 8, NULL, &end);
+	tt_int_op(pos.pos, ==, -1);
+
+	/* Searh range is after the end of the buffer */
+	tt_int_op(evbuffer_ptr_set(buf, &end, 10000, EVBUFFER_PTR_SET), ==, 0);
+	tt_int_op(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET), ==, 0);
+	pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
+	tt_int_op(pos.pos, ==, -1);
+	tt_int_op(evbuffer_ptr_set(buf, &pos, 18, EVBUFFER_PTR_SET), ==, 0);
+	pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
+	tt_int_op(pos.pos, ==, -1);
 
 end:
 	if (buf)
-- 
1.7.3.5

