From f5477c8d4522651345cba34206db821c0a43fa93 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 20 May 2026 17:02:53 +0200 Subject: [PATCH] CLEANUP: tree-wide: use array_size_or_fail() in array size for allocations Instead of relying on malloc(n*size), we now pass array_size_or_fail(n,m) so that it becomes possible to detect overflow. This is particularly interesting for global settings that might be set large enough to cause overflows on 32-bit systems for example, resulting in small values that then cause trouble. Now the overflow will be detected at allocation time. Around 25 locations were updated. --- src/cfgparse-ssl.c | 2 +- src/cfgparse.c | 4 ++-- src/cli.c | 2 +- src/errors.c | 2 +- src/fd.c | 2 +- src/haproxy.c | 2 +- src/log.c | 2 +- src/resolvers.c | 2 +- src/server.c | 6 +++--- src/sock.c | 6 +++--- src/ssl_ckch.c | 6 +++--- src/ssl_sock.c | 4 ++-- src/stats-file.c | 2 +- src/stats.c | 6 +++--- src/stick_table.c | 2 +- 15 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/cfgparse-ssl.c b/src/cfgparse-ssl.c index da88ecb81..a01d1eb9b 100644 --- a/src/cfgparse-ssl.c +++ b/src/cfgparse-ssl.c @@ -1495,7 +1495,7 @@ static int bind_parse_tls_ticket_keys(char **args, int cur_arg, struct proxy *px goto fail; } - keys_ref->tlskeys = malloc(TLS_TICKETS_NO * sizeof(union tls_sess_key)); + keys_ref->tlskeys = malloc(array_size_or_fail(TLS_TICKETS_NO, sizeof(union tls_sess_key))); if (!keys_ref->tlskeys) { memprintf(err, "'%s' : allocation error", args[cur_arg+1]); goto fail; diff --git a/src/cfgparse.c b/src/cfgparse.c index 03c788417..2e684e15d 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1394,7 +1394,7 @@ int parse_cfg(const struct cfgfile *cfg) global.cfg_curr_line = 0; global.cfg_curr_file = file; - if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) { + if ((thisline = malloc(array_size_or_fail(sizeof(*thisline), linesize))) == NULL) { ha_alert("Out of memory trying to allocate a buffer for a configuration line.\n"); err_code = -1; goto err; @@ -1442,7 +1442,7 @@ next_line: char *newline; int newlinesize = linesize * 2; - newline = realloc(thisline, sizeof(*thisline) * newlinesize); + newline = realloc(thisline, array_size_or_fail(sizeof(*thisline), newlinesize)); if (newline == NULL) { ha_alert("parsing [%s:%d]: line too long, cannot allocate memory.\n", file, linenum); diff --git a/src/cli.c b/src/cli.c index 8210985e4..eab076dde 100644 --- a/src/cli.c +++ b/src/cli.c @@ -2543,7 +2543,7 @@ static int _getsocks(char **args, char *payload, struct appctx *appctx, void *pr /* We will send sockets MAX_SEND_FD per MAX_SEND_FD, allocate a * buffer big enough to store the socket information. */ - tmpbuf = malloc(MAX_SEND_FD * (1 + MAXPATHLEN + 1 + IFNAMSIZ + sizeof(int))); + tmpbuf = malloc(array_size_or_fail(MAX_SEND_FD, (1 + MAXPATHLEN + 1 + IFNAMSIZ + sizeof(int)))); if (tmpbuf == NULL) { ha_warning("Failed to allocate memory to transfer socket information\n"); goto out; diff --git a/src/errors.c b/src/errors.c index 98e512606..f71622c0a 100644 --- a/src/errors.c +++ b/src/errors.c @@ -110,7 +110,7 @@ static void usermsgs_put(const struct ist *msg) { /* Allocate the buffer if not already done. */ if (unlikely(b_is_null(&usermsgs_buf))) { - usermsgs_buf.area = malloc(USER_MESSAGES_BUFSIZE * sizeof(char)); + usermsgs_buf.area = malloc(array_size_or_fail(USER_MESSAGES_BUFSIZE, sizeof(char))); if (usermsgs_buf.area) usermsgs_buf.size = USER_MESSAGES_BUFSIZE; } diff --git a/src/fd.c b/src/fd.c index 3d7d198ab..7b468d264 100644 --- a/src/fd.c +++ b/src/fd.c @@ -1166,7 +1166,7 @@ int init_pollers() struct poller *bp; /* always provide an aligned fdtab */ - if ((fdtab = ha_aligned_zalloc(64, global.maxsock * sizeof(*fdtab))) == NULL) { + if ((fdtab = ha_aligned_zalloc(64, array_size_or_fail(global.maxsock, sizeof(*fdtab)))) == NULL) { ha_alert("Not enough memory to allocate %d entries for fdtab!\n", global.maxsock); goto fail_tab; } diff --git a/src/haproxy.c b/src/haproxy.c index ffd969d8c..560bc1e07 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1713,7 +1713,7 @@ void haproxy_init_args(int argc, char **argv) oldpids_sig = SIGTERM; /* terminate immediately */ while (argc > 1 && argv[1][0] != '-') { char * endptr = NULL; - oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int)); + oldpids = realloc(oldpids, array_size_or_fail(nb_oldpids + 1, sizeof(int))); if (!oldpids) { ha_alert("Cannot allocate old pid : out of memory.\n"); exit(1); diff --git a/src/log.c b/src/log.c index 570cce27f..89318b82c 100644 --- a/src/log.c +++ b/src/log.c @@ -1608,7 +1608,7 @@ struct logger *dup_logger(struct logger *def) goto error; } if (def->lb.smp_rgs) { - cpy->lb.smp_rgs = malloc(sizeof(*cpy->lb.smp_rgs) * def->lb.smp_rgs_sz); + cpy->lb.smp_rgs = malloc(array_size_or_fail(sizeof(*cpy->lb.smp_rgs), def->lb.smp_rgs_sz)); if (!cpy->lb.smp_rgs) goto error; memcpy(cpy->lb.smp_rgs, def->lb.smp_rgs, diff --git a/src/resolvers.c b/src/resolvers.c index 623e5552f..07c25b2c8 100644 --- a/src/resolvers.c +++ b/src/resolvers.c @@ -3478,7 +3478,7 @@ static int parse_resolve_conf(char **errmsg, char **warnmsg) int duplicate_name = 0; int err_code = 0; - if ((resolv_line = malloc(sizeof(*resolv_line) * LINESIZE)) == NULL) { + if ((resolv_line = malloc(array_size_or_fail(sizeof(*resolv_line), LINESIZE))) == NULL) { memprintf(errmsg, "out of memory.\n"); err_code |= ERR_ALERT | ERR_FATAL; goto resolv_out; diff --git a/src/server.c b/src/server.c index ae35cc72f..23b6322bf 100644 --- a/src/server.c +++ b/src/server.c @@ -3632,7 +3632,7 @@ int srv_postinit(struct server *srv) /* initialize idle conns lists */ if (srv->max_idle_conns != 0) { - srv->curr_idle_thr = ha_aligned_zalloc(64, global.nbthread * sizeof(*srv->curr_idle_thr)); + srv->curr_idle_thr = ha_aligned_zalloc(64, array_size_or_fail(global.nbthread, sizeof(*srv->curr_idle_thr))); if (!srv->curr_idle_thr) { ha_alert("memory error during idle conn list init for %s/%s server\n", srv->proxy->id, srv->id); @@ -6106,8 +6106,8 @@ static int srv_init_per_thr(struct server *srv) { int i; - srv->per_thr = ha_aligned_zalloc(64, global.nbthread * sizeof(*srv->per_thr)); - srv->per_tgrp = ha_aligned_zalloc(64, global.nbtgroups * sizeof(*srv->per_tgrp)); + srv->per_thr = ha_aligned_zalloc(64, array_size_or_fail(global.nbthread, sizeof(*srv->per_thr))); + srv->per_tgrp = ha_aligned_zalloc(64, array_size_or_fail(global.nbtgroups, sizeof(*srv->per_tgrp))); if (!srv->per_thr || !srv->per_tgrp) return -1; diff --git a/src/sock.c b/src/sock.c index a828f7895..df387e4e8 100644 --- a/src/sock.c +++ b/src/sock.c @@ -533,7 +533,7 @@ int sock_get_old_sockets(const char *unixsocket) } memset(&msghdr, 0, sizeof(msghdr)); - cmsgbuf = malloc(CMSG_SPACE(sizeof(int)) * MAX_SEND_FD); + cmsgbuf = malloc(array_size_or_fail(CMSG_SPACE(sizeof(int)), MAX_SEND_FD)); if (!cmsgbuf) { ha_warning("Failed to allocate memory to send sockets\n"); goto out; @@ -561,13 +561,13 @@ int sock_get_old_sockets(const char *unixsocket) goto out; } - tmpbuf = malloc(fd_nb * (1 + MAXPATHLEN + 1 + IFNAMSIZ + sizeof(int))); + tmpbuf = malloc(array_size_or_fail(fd_nb, (1 + MAXPATHLEN + 1 + IFNAMSIZ + sizeof(int)))); if (tmpbuf == NULL) { ha_warning("Failed to allocate memory while receiving sockets\n"); goto out; } - tmpfd = malloc(fd_nb * sizeof(int)); + tmpfd = malloc(array_size_or_fail(fd_nb, sizeof(int))); if (tmpfd == NULL) { ha_warning("Failed to allocate memory while receiving sockets\n"); goto out; diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c index e7544b5bf..d612c9d02 100644 --- a/src/ssl_ckch.c +++ b/src/ssl_ckch.c @@ -1099,7 +1099,7 @@ struct ckch_store *ckchs_dup(const struct ckch_store *src) /* copy the array of domain strings */ while (src->conf.acme.domains[n]) { - r = my_realloc2(r, sizeof(char *) * (n + 2)); + r = my_realloc2(r, array_size_or_fail(sizeof(char *), (n + 2))); if (!r) goto error; @@ -1120,7 +1120,7 @@ struct ckch_store *ckchs_dup(const struct ckch_store *src) /* copy the array of IP strings */ while (src->conf.acme.ips[n]) { - r = my_realloc2(r, sizeof(char *) * (n + 2)); + r = my_realloc2(r, array_size_or_fail(sizeof(char *), (n + 2))); if (!r) goto error; @@ -5329,7 +5329,7 @@ int ckch_conf_parse(char **args, int cur_arg, struct ckch_conf *f, int *found, c do { while (*e != ',' && *e != '\0') e++; - r = my_realloc2(r, sizeof(char *) * (n + 2)); + r = my_realloc2(r, array_size_or_fail(sizeof(char *), (n + 2))); if (!r) { ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index ee6ddfd84..dd1b9f604 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -3743,7 +3743,7 @@ static void ssl_sock_resize_passphrase_cache(void) int idx; int new_size = passphrase_cache_size << 1; - passphrase_randoms = my_realloc2(passphrase_randoms, sizeof(*passphrase_randoms) * (new_size)); + passphrase_randoms = my_realloc2(passphrase_randoms, array_size_or_fail(sizeof(*passphrase_randoms), (new_size))); if (!passphrase_randoms) { ha_alert("ssl_sock_passwd_cb: passphrase randoms realloc failed"); passphrase_idx = -1; @@ -3759,7 +3759,7 @@ static void ssl_sock_resize_passphrase_cache(void) if (passphrase_cache_size) { passphrase_cache_size = new_size; - passphrase_cache = my_realloc2(passphrase_cache, sizeof(*passphrase_cache) * passphrase_cache_size); + passphrase_cache = my_realloc2(passphrase_cache, array_size_or_fail(sizeof(*passphrase_cache), passphrase_cache_size)); if (!passphrase_cache) { ha_alert("ssl_sock_passwd_cb: passphrase cache realloc failed"); passphrase_idx = -1; diff --git a/src/stats-file.c b/src/stats-file.c index 954b91ed6..205b886b1 100644 --- a/src/stats-file.c +++ b/src/stats-file.c @@ -417,7 +417,7 @@ void apply_stats_file(void) goto out; } - line = malloc(sizeof(char) * LINESIZE); + line = malloc(array_size_or_fail(sizeof(char), LINESIZE)); if (!line) { ha_warning("config: Can't load stats-file '%s': line alloc error.\n", global.stats_file); goto out; diff --git a/src/stats.c b/src/stats.c index d323006f1..6843f49b4 100644 --- a/src/stats.c +++ b/src/stats.c @@ -1208,7 +1208,7 @@ static int allocate_stats_px_postcheck(void) stat_cols_len[STATS_DOMAIN_PROXY] += ST_I_PX_MAX; - stat_cols[STATS_DOMAIN_PROXY] = malloc(stat_cols_len[STATS_DOMAIN_PROXY] * sizeof(struct name_desc)); + stat_cols[STATS_DOMAIN_PROXY] = malloc(array_size_or_fail(stat_cols_len[STATS_DOMAIN_PROXY], sizeof(struct name_desc))); if (!stat_cols[STATS_DOMAIN_PROXY]) { ha_alert("stats: cannot allocate all fields for proxy statistics\n"); err_code |= ERR_ALERT | ERR_FATAL; @@ -1247,7 +1247,7 @@ static int allocate_stats_rslv_postcheck(void) size_t i = 0, offset; int err_code = 0; - stat_cols[STATS_DOMAIN_RESOLVERS] = malloc(stat_cols_len[STATS_DOMAIN_RESOLVERS] * sizeof(struct name_desc)); + stat_cols[STATS_DOMAIN_RESOLVERS] = malloc(array_size_or_fail(stat_cols_len[STATS_DOMAIN_RESOLVERS], sizeof(struct name_desc))); if (!stat_cols[STATS_DOMAIN_RESOLVERS]) { ha_alert("stats: cannot allocate all fields for resolver statistics\n"); err_code |= ERR_ALERT | ERR_FATAL; @@ -1282,7 +1282,7 @@ static int allocate_stat_lines_per_thread(void) for (i = 0; i < STATS_DOMAIN_COUNT; ++i) { const int domain = domains[i]; - stat_lines[domain] = malloc(stat_cols_len[domain] * sizeof(struct field)); + stat_lines[domain] = malloc(array_size_or_fail(stat_cols_len[domain], sizeof(struct field))); if (!stat_lines[domain]) return 0; } diff --git a/src/stick_table.c b/src/stick_table.c index 0a33a775e..6bc8f172f 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -5978,7 +5978,7 @@ static int stkt_create_stk_ctr_pool(void) if (!global.tune.nb_stk_ctr) return 0; - pool_head_stk_ctr = create_pool("stk_ctr", sizeof(*((struct session*)0)->stkctr) * global.tune.nb_stk_ctr, MEM_F_SHARED); + pool_head_stk_ctr = create_pool("stk_ctr", array_size_or_fail(sizeof(*((struct session*)0)->stkctr), global.tune.nb_stk_ctr), MEM_F_SHARED); if (!pool_head_stk_ctr) { ha_alert("out of memory while creating the stick-counters pool.\n"); return ERR_ABORT;