From 58565fb93d5dc99cb572441b1e84fc56302cdd6c Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Sun, 4 Jun 2023 12:43:14 +0200 Subject: [PATCH] bufq: make write/pass methods more robust - related to #11242 where curl enters busy loop when sending http2 data to the server Closes #11247 --- lib/bufq.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/lib/bufq.c b/lib/bufq.c index 30598cf5864158..e2107f94bf8e76 100644 --- a/lib/bufq.c +++ b/lib/bufq.c @@ -418,7 +418,8 @@ ssize_t Curl_bufq_write(struct bufq *q, break; } n = chunk_append(tail, buf, len); - DEBUGASSERT(n); + if(!n) + break; nwritten += n; buf += n; len -= n; @@ -528,6 +529,14 @@ ssize_t Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer, } break; } + if(!chunk_written) { + if(!nwritten) { + /* treat as blocked */ + *err = CURLE_AGAIN; + nwritten = -1; + } + break; + } Curl_bufq_skip(q, (size_t)chunk_written); nwritten += chunk_written; } @@ -551,7 +560,8 @@ ssize_t Curl_bufq_write_pass(struct bufq *q, /* real error, fail */ return -1; } - /* would block */ + /* would block, bufq is full, give up */ + break; } } @@ -562,16 +572,24 @@ ssize_t Curl_bufq_write_pass(struct bufq *q, /* real error, fail */ return -1; } - /* no room in bufq, bail out */ - goto out; + /* no room in bufq */ + break; } + /* edge case of writer returning 0 (and len is >0) + * break or we might enter an infinite loop here */ + if(n == 0) + break; + /* Maybe only part of `data` has been added, continue to loop */ buf += (size_t)n; len -= (size_t)n; nwritten += (size_t)n; } -out: + if(!nwritten && len) { + *err = CURLE_AGAIN; + return -1; + } return nwritten; }