libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

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:
Msrc/mhd2/h2/h2_req_items_funcs.c | 46+++++++++++++++++++++++++++++++++++-----------
Msrc/mhd2/h2/h2_req_items_funcs.h | 6++++--
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)