summaryrefslogtreecommitdiff
path: root/buffer.c
diff options
context:
space:
mode:
authorAzat Khuzhin <azat@libevent.org>2019-03-03 16:29:52 +0300
committerAzat Khuzhin <azat@libevent.org>2019-03-03 18:55:25 +0300
commit5b19c9f62beb506ae0aaa507c2358c52a0a91e2a (patch)
tree3ac478aeaee9d519359dca2098a124186910ea06 /buffer.c
parentfdfabbec00b36bc6d5e69b5d8719e70d6f4e5b7b (diff)
downloadlibevent-5b19c9f62beb506ae0aaa507c2358c52a0a91e2a.tar.gz
buffer: do not rely on ->off in advance_last_with_data()
advance_last_with_data() adjusts evbuffer.last_with_datap, and if we will have empty chain in the middle advance_last_with_data() will stop, while it should not, since while empty chains is not regular thing they can pops up in various places like, and while I did not look through all of them the most tricky I would say is: evbuffer_reverse_space()/evbuffer_commit_space() evbuffer_add_reference() Test case from: https://github.com/envoyproxy/envoy/pull/6062 Fixes: #778 v2: keep last_with_datap really last with data, i.e. update only if chain has data in it
Diffstat (limited to 'buffer.c')
-rw-r--r--buffer.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/buffer.c b/buffer.c
index 7a8c8b69..8e947892 100644
--- a/buffer.c
+++ b/buffer.c
@@ -704,13 +704,17 @@ static int
advance_last_with_data(struct evbuffer *buf)
{
int n = 0;
+ struct evbuffer_chain **chainp = buf->last_with_datap;
+
ASSERT_EVBUFFER_LOCKED(buf);
- if (!*buf->last_with_datap)
+ if (!*chainp)
return 0;
- while ((*buf->last_with_datap)->next && (*buf->last_with_datap)->next->off) {
- buf->last_with_datap = &(*buf->last_with_datap)->next;
+ while ((*chainp)->next) {
+ chainp = &(*chainp)->next;
+ if ((*chainp)->off)
+ buf->last_with_datap = chainp;
++n;
}
return n;