commit 85ae67a1e0c2f068cc06d851c355b9054552444c
parent 4b8169156d654efdd4b1e5b10056e2ed6dd7f966
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Tue, 4 Aug 2026 17:44:25 +0200
mhd_h2_items_block_create(): explicitly reject incompatible sizes instead of reducing them, extra debug checks
Diffstat:
2 files changed, 39 insertions(+), 13 deletions(-)
diff --git a/src/mhd2/h2/h2_req_items_funcs.c b/src/mhd2/h2/h2_req_items_funcs.c
@@ -49,6 +49,7 @@
#include "mhd_align.h"
#include "mhd_predict.h"
#include "mhd_constexpr.h"
+#include "mhd_assume.h"
#include "mhd_assert.h"
@@ -81,6 +82,7 @@ struct mhd_H2ReqItemsBlock
#ifndef NDEBUG
uint_least32_t stream_id;
+ bool inited;
bool buff_locked;
#endif /* ! NDEBUG */
};
@@ -90,6 +92,7 @@ mhd_constexpr size_t mhd_rii_size = sizeof (struct mhd_H2ReqItem);
mhd_static_inline char *
h2_ib_get_buff (struct mhd_H2ReqItemsBlock *ib)
{
+ mhd_assert (ib->inited);
mhd_assert (ib->start_free <= ib->buf_size);
return (char *)(ib + 1u);
}
@@ -98,6 +101,7 @@ h2_ib_get_buff (struct mhd_H2ReqItemsBlock *ib)
mhd_static_inline const char *
h2_ib_get_buffc (const struct mhd_H2ReqItemsBlock *ib)
{
+ mhd_assert (ib->inited);
mhd_assert (ib->start_free <= ib->buf_size);
return (const char *)(ib + 1u);
}
@@ -148,6 +152,7 @@ h2_ib_get_n_itemc (const struct mhd_H2ReqItemsBlock *ib,
mhd_static_inline size_t
h2_ib_get_buff_free_size (const struct mhd_H2ReqItemsBlock *ib)
{
+ mhd_assert (ib->inited);
mhd_assert (ib->buf_size >= (ib->start_free
+ ib->num_items * sizeof(struct mhd_H2ReqItem)));
return ib->buf_size - ib->start_free - (ib->num_items * mhd_rii_size);
@@ -167,20 +172,24 @@ struct mhd_H2ReqItemsBlock *
mhd_h2_items_block_create (size_t buffer_size)
{
struct mhd_H2ReqItemsBlock *ret;
+ uint_fast32_t buf_size_u32;
uint_fast32_t buf_alloc_size;
+ size_t malloc_size;
- buf_alloc_size = (buffer_size & 0xFFFFFFFFu);
if (mhd_COND_HARDLY_EVER ((0xFFFFFFFFu
- 2u * mhd_ALIGNOF (struct mhd_H2ReqItem))
< buffer_size))
- buf_alloc_size =
- (uint_fast32_t)(0xFFFFFFFFu - 2 * mhd_ALIGNOF (struct mhd_H2ReqItem));
+ return NULL;
+
+ buf_size_u32 = (uint_fast32_t)(buffer_size & 0xFFFFFFFFu);
+ mhd_ASSUME (buffer_size == buf_size_u32);
/* Round up to alignment */
- buf_alloc_size +=
- (uint_fast32_t)
+ buf_alloc_size =
+ buf_size_u32
+ + (uint_fast32_t)
((mhd_ALIGNOF (struct mhd_H2ReqItem)
- - (buf_alloc_size % mhd_ALIGNOF (struct mhd_H2ReqItem)))
+ - (buf_size_u32 % mhd_ALIGNOF (struct mhd_H2ReqItem)))
% mhd_ALIGNOF (struct mhd_H2ReqItem));
/* Adjust the allocation size in case if alignment of mhd_H2ReqItem is
@@ -191,17 +200,22 @@ mhd_h2_items_block_create (size_t buffer_size)
- (sizeof(*ret) % mhd_ALIGNOF (struct mhd_H2ReqItem)))
% mhd_ALIGNOF (struct mhd_H2ReqItem));
- mhd_assert ((buffer_size <= buf_alloc_size) \
- || (0xFFFFFFFFu - 2 * mhd_ALIGNOF (struct mhd_H2ReqItem) \
- <= buf_alloc_size));
+ mhd_assert (buffer_size <= buf_alloc_size);
+
+ malloc_size = sizeof (*ret) + (size_t)buf_alloc_size;
+ if (mhd_COND_HARDLY_EVER (buf_alloc_size > malloc_size))
+ return NULL; /* Overflow or truncation on a less-than-64-bit platform */
- ret = (struct mhd_H2ReqItemsBlock *)malloc (sizeof (*ret) + buf_alloc_size);
+ mhd_assert (buffer_size < malloc_size);
+
+ ret = (struct mhd_H2ReqItemsBlock *)malloc (malloc_size);
if (NULL == ret)
return NULL; /* Failure exit point */
ret->buf_size = (size_t)buf_alloc_size;
#ifndef NDEBUG
+ ret->inited = false;
ret->buff_locked = false;
#endif /* ! NDEBUG */
mhd_h2_items_block_reset (ret);
@@ -213,6 +227,10 @@ mhd_h2_items_block_create (size_t buffer_size)
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
mhd_h2_items_block_destroy (struct mhd_H2ReqItemsBlock *ib)
{
+ mhd_assert (ib->inited);
+#ifndef NDEBUG
+ ib->inited = false;
+#endif /* ! NDEBUG */
free (ib);
}
@@ -221,13 +239,14 @@ MHD_INTERNAL
MHD_FN_PAR_INOUT_ (1) void
mhd_h2_items_block_reset (struct mhd_H2ReqItemsBlock *restrict ib)
{
- mhd_assert (ib->start_free <= ib->buf_size);
+ mhd_assert ((!ib->inited) || (ib->start_free <= ib->buf_size));
mhd_assert (!ib->buff_locked);
ib->num_items = 0u;
ib->start_free = 0u;
#ifndef NDEBUG
+ ib->inited = true;
ib->stream_id = 0u;
#endif /* ! NDEBUG */
}
@@ -348,6 +367,7 @@ MHD_INTERNAL
MHD_FN_PAR_INOUT_ (1) MHD_FN_PAR_NONNULL_ALL_ void
mhd_h2_items_cancel_new_item_buff (struct mhd_H2ReqItemsBlock *restrict ib)
{
+ mhd_assert (ib->inited);
mhd_assert (ib->buff_locked);
ib->buff_locked = false;
}
@@ -376,6 +396,7 @@ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PURE_ struct mhd_H2ReqItem *
mhd_h2_items_get_item_n (struct mhd_H2ReqItemsBlock *restrict ib,
size_t pos)
{
+ mhd_assert (ib->inited);
if (ib->num_items <= pos)
return NULL;
return h2_ib_get_n_item (ib,
@@ -387,6 +408,7 @@ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PURE_ const struct mhd_H2ReqItem *
mhd_h2_items_get_item_nc (const struct mhd_H2ReqItemsBlock *restrict ib,
size_t pos)
{
+ mhd_assert (ib->inited);
if (ib->num_items <= pos)
return NULL;
return h2_ib_get_n_itemc (ib,
@@ -485,6 +507,7 @@ MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void
mhd_h2_items_debug_set_streamid (struct mhd_H2ReqItemsBlock *restrict ib,
uint_least32_t stream_id)
{
+ mhd_assert (ib->inited);
ib->stream_id = stream_id;
}
@@ -492,6 +515,7 @@ mhd_h2_items_debug_set_streamid (struct mhd_H2ReqItemsBlock *restrict ib,
MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ uint_least32_t
mhd_h2_items_debug_get_streamid (struct mhd_H2ReqItemsBlock *restrict ib)
{
+ mhd_assert (ib->inited);
return ib->stream_id;
}
diff --git a/src/mhd2/h2/h2_req_items_funcs.h b/src/mhd2/h2/h2_req_items_funcs.h
@@ -64,9 +64,11 @@ MHD_FN_PAR_NONNULL_ALL_;
/**
* Create request items block
- * @param buffer_size the size of the items block, must be less than UINT32_MAX
+ * @param buffer_size the minimal size of the items block,
+ * must be less than UINT32_MAX minus 32, the real space
+ * in the allocated block could be rounded up
* @return the pointer to the new request items block if succeed,
- * NULL if failed (out of memory)
+ * NULL if failed (out of memory, too large @p buffer_size)
*/
MHD_INTERNAL struct mhd_H2ReqItemsBlock *
mhd_h2_items_block_create (size_t buffer_size)