commit 41bcb750d7ee0c01459be210886dad00a50e54d6
parent c4ffd734e441eab72fea517c6b8a5744c9e4b069
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Mon, 17 Aug 2026 10:31:26 +0200
HTTP/2: fixed use of too large output size when limited by pool size
Diffstat:
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/src/mhd2/h2/h2_reply_funcs.c b/src/mhd2/h2/h2_reply_funcs.c
@@ -445,6 +445,7 @@ stream_content_send (struct mhd_H2Stream *s)
size_t payload_used;
int_least32_t wndw_limit;
uint_least32_t full_payload_limit;
+ uint_least32_t payload_size_limit;
mhd_assert (mhd_H2_RPL_STAGE_HEADERS_COMPLETE == s->rpl.stage);
mhd_assert (s->rpl.send_content);
@@ -469,10 +470,6 @@ stream_content_send (struct mhd_H2Stream *s)
else
cntnt_left = MHD_SIZE_UNKNOWN;
- if ((min_size_for_data > full_payload_limit)
- && (cntnt_left != full_payload_limit))
- return false;
-
dat = mhd_h2_frame_init_data (&h2frame,
s->stream_id,
false); /* could be updated below */
@@ -488,13 +485,30 @@ stream_content_send (struct mhd_H2Stream *s)
pld_buff_size = buff.size - payload_offset;
mhd_assert (mhd_H2_FR_HDR_BASE_SIZE < pld_buff_size);
+ /* The acquired buffer could be smaller than the requested limit.
+ The payload of this frame is limited by the acquired buffer. */
+ payload_size_limit = full_payload_limit;
+ if (pld_buff_size < payload_size_limit)
+ payload_size_limit = (uint_least32_t)pld_buff_size;
+
+ if ((min_size_for_data > payload_size_limit)
+ && (cntnt_left != payload_size_limit)
+ && (mhd_RESPONSE_CONTENT_DATA_CALLBACK != r->cntn_dtype))
+ { /* The acquired space is too small to be used efficiently.
+ The callback content is not limited: the application may provide
+ the data in small portions. */
+ mhd_h2_out_buff_unlock (s->c,
+ 0u);
+ return false;
+ }
+
mhd_assert (r->cntn_size > s->rpl.cntn_read_pos);
payload_used = 0u;
switch (r->cntn_dtype)
{
case mhd_RESPONSE_CONTENT_DATA_BUFFER:
- payload_used = (size_t)full_payload_limit;
+ payload_used = (size_t)payload_size_limit;
memcpy (pld_buff,
r->cntn.buf + s->rpl.cntn_read_pos,
payload_used);
@@ -502,7 +516,7 @@ stream_content_send (struct mhd_H2Stream *s)
case mhd_RESPONSE_CONTENT_DATA_IOVEC:
if (!content_read_iovec (r,
s->rpl.cntn_read_pos,
- pld_buff_size,
+ (size_t)payload_size_limit,
pld_buff,
&payload_used))
payload_used = 0u;
@@ -510,7 +524,7 @@ stream_content_send (struct mhd_H2Stream *s)
case mhd_RESPONSE_CONTENT_DATA_FILE:
if (!content_read_file (r,
s->rpl.cntn_read_pos,
- pld_buff_size,
+ (size_t)payload_size_limit,
pld_buff,
&payload_used))
payload_used = 0u;