]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
bufq: make write/pass methods more robust
authorStefan Eissing <stefan@eissing.org>
Sun, 4 Jun 2023 10:43:14 +0000 (12:43 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 5 Jun 2023 18:11:41 +0000 (20:11 +0200)
- related to #11242 where curl enters busy loop when
  sending http2 data to the server

Closes #11247

lib/bufq.c

index 30598cf5864158e9c0c3669e2f2b5d471b650153..e2107f94bf8e76bcbed461b482711defe196d910 100644 (file)
@@ -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;
 }