commit 75f0be5f084c39e6596c4f1ead827d30509ab60f
parent 1b215e49d37329b6c70c72d1b0518fa7fcb112e5
Author: Evgeny Grin (Karlson2k) <k2k@drgrin.dev>
Date: Sat, 27 Jun 2026 20:19:35 +0200
Added checks for size overflows in response header building
Diffstat:
1 file changed, 46 insertions(+), 9 deletions(-)
diff --git a/src/mhd2/stream_process_reply.c b/src/mhd2/stream_process_reply.c
@@ -54,6 +54,7 @@
#include "mhd_assert.h"
#include "mhd_unreachable.h"
+#include "mhd_predict.h"
#include <string.h>
#ifdef HAVE_TIME_H
@@ -519,6 +520,8 @@ buffer_append (char *buf,
size_t append_size)
{
mhd_assert (NULL != buf); /* Mute static analyzer */
+ if (mhd_COND_HARDLY_EVER (*ppos + append_size < append_size)) /* Check for overflow */
+ return false;
if (buf_size < *ppos + append_size)
return false;
memcpy (buf + *ppos, append, append_size);
@@ -585,7 +588,17 @@ add_user_headers (char *restrict buf,
}
/* Add user header */
- el_size = hdr->name.len + 2 + hdr->value.len + 2;
+ el_size = hdr->name.len + 2u;
+ if (mhd_COND_ALMOST_NEVER (2u > el_size)) /* Check for overflow */
+ return false;
+ el_size += hdr->value.len;
+ if (mhd_COND_ALMOST_NEVER (hdr->value.len > el_size)) /* Check for overflow */
+ return false;
+ el_size += 2u;
+ if (mhd_COND_ALMOST_NEVER (2u > el_size)) /* Check for overflow */
+ return false;
+ if (mhd_COND_HARDLY_EVER (*ppos + el_size < el_size)) /* Check for overflow */
+ return false;
if (buf_size < *ppos + el_size)
return false;
memcpy (buf + *ppos, hdr->name.cstr, hdr->name.len);
@@ -601,21 +614,31 @@ add_user_headers (char *restrict buf,
if (add_close)
{
- el_size += mhd_SSTR_LEN ("close, ");
+ static const struct MHD_String cn_add = mhd_MSTR_INIT ("close, ");
+ el_size += cn_add.len;
+ if (mhd_COND_ALMOST_NEVER (cn_add.len > el_size)) /* Check for overflow */
+ return false;
+ if (mhd_COND_HARDLY_EVER (initial_pos + el_size < el_size)) /* Check for overflow */
+ return false;
if (buf_size < initial_pos + el_size)
return false;
- memcpy (buf + *ppos, "close, ",
- mhd_SSTR_LEN ("close, "));
- *ppos += mhd_SSTR_LEN ("close, ");
+ memcpy (buf + *ppos, cn_add.cstr,
+ cn_add.len);
+ *ppos += cn_add.len;
}
else
{
- el_size += mhd_SSTR_LEN ("Keep-Alive, ");
+ static const struct MHD_String cn_add = mhd_MSTR_INIT ("Keep-Alive, ");
+ el_size += cn_add.len;
+ if (mhd_COND_ALMOST_NEVER (cn_add.len > el_size)) /* Check for overflow */
+ return false;
+ if (mhd_COND_HARDLY_EVER (initial_pos + el_size < el_size)) /* Check for overflow */
+ return false;
if (buf_size < initial_pos + el_size)
return false;
- memcpy (buf + *ppos, "Keep-Alive, ",
- mhd_SSTR_LEN ("Keep-Alive, "));
- *ppos += mhd_SSTR_LEN ("Keep-Alive, ");
+ memcpy (buf + *ppos, cn_add.cstr,
+ cn_add.len);
+ *ppos += cn_add.len;
}
add_close = false;
add_keep_alive = false;
@@ -772,6 +795,8 @@ build_header_response_inn (struct MHD_Connection *restrict c)
}
/* The response code */
+ if (mhd_COND_HARDLY_EVER (pos + 5 < 5)) /* Check for overflow */
+ return false;
if (buf_size < pos + 5) /* space + code + space */
return false;
buf[pos++] = ' ';
@@ -791,6 +816,8 @@ build_header_response_inn (struct MHD_Connection *restrict c)
return false;
}
/* The linefeed */
+ if (mhd_COND_HARDLY_EVER (pos + 2 < 2)) /* Check for overflow */
+ return false;
if (buf_size < pos + 2)
return false;
buf[pos++] = '\r';
@@ -802,6 +829,10 @@ build_header_response_inn (struct MHD_Connection *restrict c)
if (0 != r->special_resp.spec_hdr_len)
{
mhd_assert (r->cfg.int_err_resp);
+ if (mhd_COND_HARDLY_EVER (r->special_resp.spec_hdr_len + 2 < 2)) /* Check for overflow */
+ return false;
+ if (mhd_COND_HARDLY_EVER (pos + r->special_resp.spec_hdr_len + 2 < pos)) /* Check for overflow */
+ return false;
if (buf_size < pos + r->special_resp.spec_hdr_len + 2)
return false;
memcpy (buf + pos,
@@ -819,6 +850,8 @@ build_header_response_inn (struct MHD_Connection *restrict c)
(! c->daemon->req_cfg.suppress_date) )
{
/* Additional byte for unused zero-termination */
+ if (mhd_COND_HARDLY_EVER (pos + 38 < 38)) /* Check for overflow */
+ return false;
if (buf_size < pos + 38)
return false;
if (get_date_header (buf + pos))
@@ -916,6 +949,8 @@ build_header_response_inn (struct MHD_Connection *restrict c)
return false;
pos += el_size;
+ if (pos + 2 < 2) /* Check for overflow */
+ return false;
if (buf_size < pos + 2)
return false;
buf[pos++] = '\r';
@@ -932,6 +967,8 @@ build_header_response_inn (struct MHD_Connection *restrict c)
}
/* * Header termination * */
+ if (mhd_COND_HARDLY_EVER (pos + 2 < 2)) /* Check for overflow */
+ return false;
if (buf_size < pos + 2)
return false;
buf[pos++] = '\r';