From: Stefan Eissing Date: Tue, 7 Oct 2025 09:30:46 +0000 (+0200) Subject: ngtcp2: fix handling of blocked stream data X-Git-Tag: rc-8_17_0-1~77 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=88a1ab511ce0883c0c0429a74af754036cff5df8;p=thirdparty%2Fcurl.git ngtcp2: fix handling of blocked stream data The stream blocking might not be the one of the current easy handle. Look up the stream to be marked as blocking via its stream_id in the internal hash. Theoretically, this does not have to be one of the h3 streams, so not finding it is not an error. Fixes #18905 Reported-by: Joshua Rogers Closes #18906 --- diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index af7f26eb39..b48d1af555 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -300,6 +300,35 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, return CURLE_OK; } +struct cf_ngtcp2_sfind_ctx { + curl_int64_t stream_id; + struct h3_stream_ctx *stream; + unsigned int mid; +}; + +static bool cf_ngtcp2_sfind(unsigned int mid, void *value, void *user_data) +{ + struct cf_ngtcp2_sfind_ctx *fctx = user_data; + struct h3_stream_ctx *stream = value; + + if(fctx->stream_id == stream->id) { + fctx->mid = mid; + fctx->stream = stream; + return FALSE; + } + return TRUE; /* continue */ +} + +static struct h3_stream_ctx * +cf_ngtcp2_get_stream(struct cf_ngtcp2_ctx *ctx, curl_int64_t stream_id) +{ + struct cf_ngtcp2_sfind_ctx fctx; + fctx.stream_id = stream_id; + fctx.stream = NULL; + Curl_uint_hash_visit(&ctx->streams, cf_ngtcp2_sfind, &fctx); + return fctx.stream; +} + static void cf_ngtcp2_stream_close(struct Curl_cfilter *cf, struct Curl_easy *data, struct h3_stream_ctx *stream) @@ -1808,13 +1837,13 @@ static CURLcode read_pkt_to_send(void *userp, else if(n < 0) { switch(n) { case NGTCP2_ERR_STREAM_DATA_BLOCKED: { - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, x->data); + struct h3_stream_ctx *stream; DEBUGASSERT(ndatalen == -1); nghttp3_conn_block_stream(ctx->h3conn, stream_id); CURL_TRC_CF(x->data, x->cf, "[%" FMT_PRId64 "] block quic flow", (curl_int64_t)stream_id); - DEBUGASSERT(stream); - if(stream) + stream = cf_ngtcp2_get_stream(ctx, stream_id); + if(stream) /* it might be not one of our h3 streams? */ stream->quic_flow_blocked = TRUE; n = 0; break;