]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http2: ingress handling edge cases
authorStefan Eissing <stefan@eissing.org>
Wed, 8 Oct 2025 11:06:48 +0000 (13:06 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 9 Oct 2025 06:43:34 +0000 (08:43 +0200)
Fix some edge cases around the `data_max_bytes` handling when
processing ingress.

Reported-by: Joshua Rogers
Closes #18933

lib/http2.c

index 43f4e9106cafeb1ca1165f425ac2e24667825ca3..4e2d59ff518776906488f04d2c146b138e383a80 100644 (file)
@@ -623,9 +623,8 @@ static int should_close_session(struct cf_h2_ctx *ctx)
  * This function returns 0 if it succeeds, or -1 and error code will
  * be assigned to *err.
  */
-static int h2_process_pending_input(struct Curl_cfilter *cf,
-                                    struct Curl_easy *data,
-                                    CURLcode *err)
+static CURLcode h2_process_pending_input(struct Curl_cfilter *cf,
+                                         struct Curl_easy *data)
 {
   struct cf_h2_ctx *ctx = cf->ctx;
   const unsigned char *buf;
@@ -633,12 +632,10 @@ static int h2_process_pending_input(struct Curl_cfilter *cf,
   ssize_t rv;
 
   while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) {
-
     rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen);
     if(rv < 0) {
       failf(data, "nghttp2 recv error %zd: %s", rv, nghttp2_strerror((int)rv));
-      *err = CURLE_HTTP2;
-      return -1;
+      return CURLE_HTTP2;
     }
     Curl_bufq_skip(&ctx->inbufq, (size_t)rv);
     if(Curl_bufq_is_empty(&ctx->inbufq)) {
@@ -658,7 +655,7 @@ static int h2_process_pending_input(struct Curl_cfilter *cf,
     connclose(cf->conn, "http/2: No new requests allowed");
   }
 
-  return 0;
+  return CURLE_OK;
 }
 
 /*
@@ -690,7 +687,8 @@ static bool http2_connisalive(struct Curl_cfilter *cf, struct Curl_easy *data,
     if(!result) {
       CURL_TRC_CF(data, cf, "%zu bytes stray data read before trying "
                   "h2 connection", nread);
-      if(h2_process_pending_input(cf, data, &result) < 0)
+      result = h2_process_pending_input(cf, data);
+      if(result)
         /* immediate error, considered dead */
         alive = FALSE;
       else {
@@ -2045,10 +2043,14 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
   if(!Curl_bufq_is_empty(&ctx->inbufq)) {
     CURL_TRC_CF(data, cf, "Process %zu bytes in connection buffer",
                 Curl_bufq_len(&ctx->inbufq));
-    if(h2_process_pending_input(cf, data, &result) < 0)
+    result = h2_process_pending_input(cf, data);
+    if(result)
       return result;
   }
 
+  if(!data_max_bytes)
+    data_max_bytes = H2_CHUNK_SIZE;
+
   /* Receive data from the "lower" filters, e.g. network until
    * it is time to stop due to connection close or us not processing
    * all network input */
@@ -2063,6 +2065,10 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
         Curl_multi_mark_dirty(data);
       break;
     }
+    else if(!stream) {
+      DEBUGASSERT(0);
+      break;
+    }
 
     result = Curl_cf_recv_bufq(cf->next, data, &ctx->inbufq, 0, &nread);
     if(result) {
@@ -2083,7 +2089,8 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf,
       data_max_bytes = (data_max_bytes > nread) ? (data_max_bytes - nread) : 0;
     }
 
-    if(h2_process_pending_input(cf, data, &result))
+    result = h2_process_pending_input(cf, data);
+    if(result)
       return result;
     CURL_TRC_CF(data, cf, "[0] progress ingress: inbufg=%zu",
                 Curl_bufq_len(&ctx->inbufq));
@@ -2546,7 +2553,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf,
   }
 
   if(!first_time) {
-    result = h2_progress_ingress(cf, data, H2_CHUNK_SIZE);
+    result = h2_progress_ingress(cf, data, 0);
     if(result)
       goto out;
   }