summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-15 15:58:31 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-15 15:58:31 -0600
commitdb9a58f48c6eae16fbfcd89d59b09e123dbed54f (patch)
tree8e20dd9bc3ddf7b766714a57a9d33259c0b91165
parent03f29736acfcfaee6f263fd1461f96ccae3696da (diff)
libmisc: Add alloc.h to help detect wrong alloc sizes
Lo and behold, there was a mistake in chan.c.
-rw-r--r--cmd/sbc_harness/fs_harness_uptime_txt.c4
-rw-r--r--lib9p/srv.c4
-rw-r--r--lib9p/tests/test_server/fs_shutdown.c4
-rw-r--r--lib9p/tests/test_server/fs_slowread.c4
-rw-r--r--lib9p/tests/test_server/fs_whoami.c6
-rw-r--r--libcr_ipc/chan.c4
-rw-r--r--libhw_cr/host_net.c3
-rw-r--r--libhw_cr/rp2040_hwspi.c6
-rw-r--r--libhw_cr/w5500_ll.h6
-rw-r--r--libmisc/include/libmisc/alloc.h26
-rw-r--r--libmisc/map.c3
11 files changed, 50 insertions, 20 deletions
diff --git a/cmd/sbc_harness/fs_harness_uptime_txt.c b/cmd/sbc_harness/fs_harness_uptime_txt.c
index 1425bf9..dd5c681 100644
--- a/cmd/sbc_harness/fs_harness_uptime_txt.c
+++ b/cmd/sbc_harness/fs_harness_uptime_txt.c
@@ -5,10 +5,10 @@
*/
#include <stdio.h> /* for snprintf() */
-#include <stdlib.h> /* for malloc(), free() */
#include <libhw/generic/alarmclock.h>
#include <util9p/static.h>
+#include <libmisc/alloc.h> /* for heap_alloc(), free() */
#include "fs_harness_uptime_txt.h"
@@ -91,7 +91,7 @@ static lo_interface lib9p_srv_fio uptime_file_fopen(struct uptime_file *self, st
assert(self);
assert(ctx);
- struct uptime_fio *ret = malloc(sizeof(struct uptime_fio));
+ struct uptime_fio *ret = heap_alloc(1, struct uptime_fio);
ret->parent = self;
ret->buf_len = 0;
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 5c50130..a681952 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <alloca.h>
#include <inttypes.h> /* for PRI* */
#include <limits.h> /* for SSIZE_MAX, not set by newlib */
#include <stddef.h> /* for size_t */
@@ -17,6 +16,7 @@
#include <libcr/coroutine.h>
#include <libcr_ipc/chan.h>
#include <libcr_ipc/mutex.h>
+#include <libmisc/alloc.h>
#include <libmisc/assert.h>
#include <libmisc/endian.h>
#include <libmisc/map.h>
@@ -739,7 +739,7 @@ static void handle_Tversion(struct srv_req *ctx,
if (map_len(&ctx->parent_sess->reqs)) {
/* Flush all in-progress requests, and wait for them
* to finish. */
- struct cr_select_arg *list = alloca(sizeof(struct cr_select_arg) * map_len(&ctx->parent_sess->reqs));
+ struct cr_select_arg *list = stack_alloc(map_len(&ctx->parent_sess->reqs), struct cr_select_arg);
while (map_len(&ctx->parent_sess->reqs)) {
size_t i = 0;
bool flushed;
diff --git a/lib9p/tests/test_server/fs_shutdown.c b/lib9p/tests/test_server/fs_shutdown.c
index e872b78..e7375ef 100644
--- a/lib9p/tests/test_server/fs_shutdown.c
+++ b/lib9p/tests/test_server/fs_shutdown.c
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <stdlib.h>
+#include <libmisc/alloc.h>
#include "fs_shutdown.h"
@@ -68,7 +68,7 @@ static lo_interface lib9p_srv_fio shutdown_file_fopen(struct shutdown_file *self
assert(self);
assert(ctx);
- struct shutdown_fio *ret = malloc(sizeof(struct shutdown_fio));
+ struct shutdown_fio *ret = heap_alloc(1, struct shutdown_fio);
ret->parent = self;
return lo_box_shutdown_fio_as_lib9p_srv_fio(ret);
diff --git a/lib9p/tests/test_server/fs_slowread.c b/lib9p/tests/test_server/fs_slowread.c
index c94fba0..4567fef 100644
--- a/lib9p/tests/test_server/fs_slowread.c
+++ b/lib9p/tests/test_server/fs_slowread.c
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <stdlib.h>
+#include <libmisc/alloc.h>
#include "fs_slowread.h"
@@ -68,7 +68,7 @@ static lo_interface lib9p_srv_fio slowread_file_fopen(struct slowread_file *self
assert(self);
assert(ctx);
- struct slowread_fio *ret = malloc(sizeof(struct slowread_fio));
+ struct slowread_fio *ret = heap_alloc(1, struct slowread_fio);
ret->parent = self;
return lo_box_slowread_fio_as_lib9p_srv_fio(ret);
diff --git a/lib9p/tests/test_server/fs_whoami.c b/lib9p/tests/test_server/fs_whoami.c
index 560e31f..653ac4b 100644
--- a/lib9p/tests/test_server/fs_whoami.c
+++ b/lib9p/tests/test_server/fs_whoami.c
@@ -5,7 +5,9 @@
*/
#include <stdio.h> /* for snprintf() */
-#include <stdlib.h> /* for malloc(), realloc(), free() */
+#include <stdlib.h> /* for realloc(), free() */
+
+#include <libmisc/alloc.h>
#include "fs_whoami.h"
@@ -89,7 +91,7 @@ static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, st
assert(self);
assert(ctx);
- struct whoami_fio *ret = malloc(sizeof(struct whoami_fio));
+ struct whoami_fio *ret = heap_alloc(1, struct whoami_fio);
ret->parent = self;
ret->buf_len = 0;
ret->buf = NULL;
diff --git a/libcr_ipc/chan.c b/libcr_ipc/chan.c
index 6cbe890..f20b8a0 100644
--- a/libcr_ipc/chan.c
+++ b/libcr_ipc/chan.c
@@ -4,10 +4,10 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <alloca.h> /* for alloca() */
#include <string.h> /* for memcpy() */
#include <libcr/coroutine.h> /* for cid_t, cr_* */
+#include <libmisc/alloc.h>
#include <libmisc/assert.h>
#include <libmisc/rand.h>
@@ -150,7 +150,7 @@ size_t cr_select_v(size_t arg_cnt, struct cr_select_arg arg_vec[]) {
struct cr_select_waiters waiters = {
.cnt = arg_cnt,
.args = arg_vec,
- .nodes = alloca(sizeof(struct cr_chan_waiter) * arg_cnt),
+ .nodes = stack_alloc(arg_cnt, struct _cr_chan_waiter_list_node),
};
for (size_t i = 0; i < arg_cnt; i++) {
waiters.nodes[i] = (struct _cr_chan_waiter_list_node){ .val = {
diff --git a/libhw_cr/host_net.c b/libhw_cr/host_net.c
index 6ed6e46..ba634a6 100644
--- a/libhw_cr/host_net.c
+++ b/libhw_cr/host_net.c
@@ -19,6 +19,7 @@
#include <signal.h> /* for siginfo_t, struct sigaction, enum sigval, sigaction(), SA_SIGINFO */
#include <libcr/coroutine.h>
+#include <libmisc/alloc.h>
#include <libmisc/assert.h>
#include <libmisc/macro.h>
#include <libobj/obj.h>
@@ -283,7 +284,7 @@ static void *hostnet_pthread_writev(void *_args) {
struct hostnet_pthread_writev_args *args = _args;
size_t count = 0;
- struct iovec *iov = alloca(sizeof(struct iovec)*args->iovcnt);
+ struct iovec *iov = stack_alloc(args->iovcnt, struct iovec);
for (int i = 0; i < args->iovcnt; i++) {
iov[i] = args->iov[i];
count += args->iov[i].iov_len;
diff --git a/libhw_cr/rp2040_hwspi.c b/libhw_cr/rp2040_hwspi.c
index d181650..29a7bac 100644
--- a/libhw_cr/rp2040_hwspi.c
+++ b/libhw_cr/rp2040_hwspi.c
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <alloca.h>
#include <inttypes.h> /* for PRIu{n} */
#include <hardware/clocks.h> /* for clock_get_hz() and clk_peri */
@@ -12,6 +11,7 @@
#include <hardware/spi.h>
#include <libcr/coroutine.h>
+#include <libmisc/alloc.h>
#include <libmisc/assert.h>
#define LOG_NAME RP2040_SPI
@@ -198,8 +198,8 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl
* happens, so the IRQ machinery doesn't need to be engaged
* at all.
*/
- struct dma_alias1 *tx_data_blocks = alloca(sizeof(struct dma_alias1)*(pruned_iovcnt+1));
- struct dma_alias0 *rx_data_blocks = alloca(sizeof(struct dma_alias0)*(pruned_iovcnt+1));
+ struct dma_alias1 *tx_data_blocks = stack_alloc(pruned_iovcnt+1, struct dma_alias1);
+ struct dma_alias0 *rx_data_blocks = stack_alloc(pruned_iovcnt+1, struct dma_alias0);
static_assert(!DMA_IS_TRIGGER(typeof(tx_data_blocks[0]), ctrl));
static_assert(DMA_IS_TRIGGER(typeof(rx_data_blocks[0]), ctrl));
diff --git a/libhw_cr/w5500_ll.h b/libhw_cr/w5500_ll.h
index 2506cd2..8b98f9d 100644
--- a/libhw_cr/w5500_ll.h
+++ b/libhw_cr/w5500_ll.h
@@ -10,10 +10,10 @@
#ifndef _LIBHW_CR_W5500_LL_H_
#define _LIBHW_CR_W5500_LL_H_
-#include <alloca.h> /* for alloca() */
#include <stdint.h> /* for uint{n}_t */
#include <string.h> /* for memcmp() */
+#include <libmisc/alloc.h> /* for stack_alloc() */
#include <libmisc/assert.h> /* for assert(), static_assert() */
#include <libmisc/endian.h> /* for uint16be_t */
@@ -94,7 +94,7 @@ w5500ll_writev(
(block & CTL_MASK_BLOCK) | CTL_W | CTL_OM_VDM,
};
int inner_cnt = 1+io_slice_cnt(iov, iovcnt, skip, max);
- struct duplex_iovec *inner = alloca(sizeof(struct duplex_iovec)*inner_cnt);
+ struct duplex_iovec *inner = stack_alloc(inner_cnt, struct duplex_iovec);
inner[0] = (struct duplex_iovec){
.iov_read_to = IOVEC_DISCARD,
.iov_write_from = header,
@@ -131,7 +131,7 @@ w5500ll_readv(
(block & CTL_MASK_BLOCK) | CTL_R | CTL_OM_VDM,
};
int inner_cnt = 1+io_slice_cnt(iov, iovcnt, 0, max);
- struct duplex_iovec *inner = alloca(sizeof(struct duplex_iovec)*inner_cnt);
+ struct duplex_iovec *inner = stack_alloc(inner_cnt, struct duplex_iovec);
inner[0] = (struct duplex_iovec){
.iov_read_to = IOVEC_DISCARD,
.iov_write_from = header,
diff --git a/libmisc/include/libmisc/alloc.h b/libmisc/include/libmisc/alloc.h
new file mode 100644
index 0000000..afddbce
--- /dev/null
+++ b/libmisc/include/libmisc/alloc.h
@@ -0,0 +1,26 @@
+/* libmisc/alloc.h - Type-safe wrappers around alloca and malloc
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIBMISC_ALLOC_H_
+#define _LIBMISC_ALLOC_H_
+
+#include <alloca.h> /* for alloca() */
+#include <stdlib.h> /* for calloc(), free() */
+#include <string.h> /* for memset() */
+
+#define stack_alloc(N, TYP) ({ \
+ size_t _size; \
+ TYP *_ret = NULL; \
+ if (!__builtin_mul_overflow(N, sizeof(TYP), &_size)) { \
+ _ret = alloca(_size); \
+ memset(_ret, 0, _size); \
+ } \
+ _ret; \
+})
+
+#define heap_alloc(N, TYP) ((TYP *)calloc(N, sizeof(TYP)))
+
+#endif /* _LIBMISC_ALLOC_H_ */
diff --git a/libmisc/map.c b/libmisc/map.c
index 7629c8c..cc34c16 100644
--- a/libmisc/map.c
+++ b/libmisc/map.c
@@ -8,6 +8,7 @@
#include <string.h>
#include <libmisc/hash.h>
+#include <libmisc/alloc.h>
#include <libmisc/assert.h>
#include <libmisc/map.h>
@@ -63,7 +64,7 @@ static inline void _map_lookup(struct _map *m, void *keyp,
static inline void _map_resize(struct _map *m, size_t new_nbuckets) {
assert(m);
assert(new_nbuckets);
- struct _map_kv_list *new_buckets = calloc(new_nbuckets, sizeof(struct _map_kv_list));
+ struct _map_kv_list *new_buckets = heap_alloc(new_nbuckets, struct _map_kv_list);
for (size_t i = 0; i < m->nbuckets; i++) {
while (m->buckets[i].front) {
struct _map_kv_list_node *kv = m->buckets[i].front;