]> granicus.if.org Git - libevent/commitdiff
Allow evbuffer_ptr to point to position 0 in an empty evbuffer
authorNir Soffer <nirsof@gmail.com>
Mon, 13 Jun 2011 20:35:28 +0000 (16:35 -0400)
committerNick Mathewson <nickm@torproject.org>
Mon, 13 Jun 2011 20:48:03 +0000 (16:48 -0400)
buffer.c
test/regress_buffer.c

index c4297ed05655e3bf325573af15d912a55635f364..9d8820e0e4274f930df97e3dbbc6c690c4d37573 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -1334,6 +1334,9 @@ evbuffer_getchr(struct evbuffer_ptr *it)
        struct evbuffer_chain *chain = it->_internal.chain;
        size_t off = it->_internal.pos_in_chain;
 
+       if (chain == NULL)
+               return -1; /* XXX Better invalid char value? */
+
        return chain->buffer[chain->misalign + off];
 }
 
@@ -1346,6 +1349,14 @@ evbuffer_search_eol(struct evbuffer *buffer,
        size_t extra_drain = 0;
        int ok = 0;
 
+       /* Avoid locking in trivial edge cases */
+       if (start && start->_internal.chain == NULL) {
+               it.pos = -1;
+               if (eol_len_out)
+                       *eol_len_out = extra_drain;
+               return it;
+       }
+
        EVBUFFER_LOCK(buffer);
 
        if (start) {
@@ -2334,9 +2345,10 @@ 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->_internal.chain = buf->last;
-               pos->_internal.pos_in_chain = buf->last->off;
+       } else if (left == 0) {
+               /* The first byte in the (nonexistent) chain after the last chain */
+               pos->_internal.chain = NULL;
+               pos->_internal.pos_in_chain = 0;
        } else {
                pos->_internal.chain = NULL;
                pos->pos = -1;
@@ -2466,6 +2478,10 @@ evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,
        int idx = 0;
        ev_ssize_t len_so_far = 0;
 
+       /* Avoid locking in trivial edge cases */
+       if (start_at && start_at->_internal.chain == NULL)
+               return 0;
+
        EVBUFFER_LOCK(buffer);
 
        if (start_at) {
index a9a4f6a3df9815976b17d0e26e9e296a5276dc52..03a27ead17c85fd6d4940aded9279b752365a1c8 100644 (file)
@@ -1090,6 +1090,12 @@ test_evbuffer_search_eol(void *ptr)
        tt_int_op(ptr2.pos, ==, 11);
        tt_int_op(eol_len, ==, 1);
 
+       tt_assert(evbuffer_ptr_set(buf, &ptr1, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
+       eol_len = -1;
+       ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
+       tt_int_op(ptr2.pos, ==, -1);
+       tt_int_op(eol_len, ==, 0);
+
 end:
        evbuffer_free(buf);
 }
@@ -1190,6 +1196,15 @@ test_evbuffer_ptr_set(void *ptr)
        struct evbuffer_ptr pos;
        struct evbuffer_iovec v[1];
 
+       tt_int_op(evbuffer_get_length(buf), ==, 0);
+
+       tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
+       tt_assert(pos.pos == 0);
+       tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_ADD) == -1);
+       tt_assert(pos.pos == -1);
+       tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_SET) == -1);
+       tt_assert(pos.pos == -1);
+
        /* create some chains */
        evbuffer_reserve_space(buf, 5000, v, 1);
        v[0].iov_len = 5000;
@@ -1239,6 +1254,18 @@ test_evbuffer_search(void *ptr)
        struct evbuffer *tmp = evbuffer_new();
        struct evbuffer_ptr pos, end;
 
+       pos = evbuffer_search(buf, "x", 1, NULL);
+       tt_int_op(pos.pos, ==, -1);
+       tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
+       pos = evbuffer_search(buf, "x", 1, &pos);
+       tt_int_op(pos.pos, ==, -1);
+       tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
+       pos = evbuffer_search_range(buf, "x", 1, &pos, &pos);
+       tt_int_op(pos.pos, ==, -1);
+       tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
+       pos = evbuffer_search_range(buf, "x", 1, &pos, NULL);
+       tt_int_op(pos.pos, ==, -1);
+
        /* set up our chains */
        evbuffer_add_printf(tmp, "hello");  /* 5 chars */
        evbuffer_add_buffer(buf, tmp);
@@ -1282,10 +1309,20 @@ test_evbuffer_search(void *ptr)
        pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
        tt_int_op(pos.pos, ==, -1);
 
-       /* Set "end" to the last byte in the buffer. */
-       evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET);
+       /* Set "end" after the last byte in the buffer. */
+       tt_assert(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);
+       tt_assert(evbuffer_ptr_set(buf, &pos, 11, EVBUFFER_PTR_SET) == 0);
+       pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
+       tt_int_op(pos.pos, ==, 11);
+       tt_assert(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_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
+       pos = evbuffer_search_range(buf, "attack", 6, &pos, NULL);
+       tt_int_op(pos.pos, ==, -1);
 
 end:
        if (buf)
@@ -1636,6 +1673,13 @@ test_evbuffer_peek(void *info)
        tt_iov_eq(&v[0], "Contents of chunk [2]\n");
        tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
 
+       /* peek at the end of the buffer */
+       memset(v, 0, sizeof(v));
+       tt_assert(evbuffer_ptr_set(buf, &ptr, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
+       i = evbuffer_peek(buf, 44, &ptr, v, 20);
+       tt_int_op(i, ==, 0);
+       tt_assert(v[0].iov_base == NULL);
+
 end:
        if (buf)
                evbuffer_free(buf);