From 4f97a679f0d51d4e92614ea41a0fd300aaac3c7c Mon Sep 17 00:00:00 2001 From: Tony Finch Date: Thu, 9 Mar 2023 10:43:53 +0000 Subject: [PATCH] A macro for the size of a struct with a flexible array member It can be fairly long-winded to allocate space for a struct with a flexible array member: in general we need the size of the struct, the size of the member, and the number of elements. Wrap them all up in a STRUCT_FLEX_SIZE() macro, and use the new macro for the flexible arrays in isc_ht and dns_qp. --- lib/dns/qp.c | 6 +++--- lib/isc/histo.c | 7 ------- lib/isc/ht.c | 4 ++-- lib/isc/include/isc/util.h | 8 ++++++++ 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/dns/qp.c b/lib/dns/qp.c index 60acf13ed5..fec71033b1 100644 --- a/lib/dns/qp.c +++ b/lib/dns/qp.c @@ -426,13 +426,13 @@ static void realloc_chunk_arrays(dns_qp_t *qp, qp_chunk_t newmax) { size_t oldptrs = sizeof(qp->base->ptr[0]) * qp->chunk_max; size_t newptrs = sizeof(qp->base->ptr[0]) * newmax; - size_t allbytes = sizeof(dns_qpbase_t) + newptrs; + size_t size = STRUCT_FLEX_SIZE(qp->base, ptr, newmax); if (qp->base == NULL || qpbase_unref(qp)) { - qp->base = isc_mem_reallocate(qp->mctx, qp->base, allbytes); + qp->base = isc_mem_reallocate(qp->mctx, qp->base, size); } else { dns_qpbase_t *oldbase = qp->base; - qp->base = isc_mem_allocate(qp->mctx, allbytes); + qp->base = isc_mem_allocate(qp->mctx, size); memmove(&qp->base->ptr[0], &oldbase->ptr[0], oldptrs); } memset(&qp->base->ptr[qp->chunk_max], 0, newptrs - oldptrs); diff --git a/lib/isc/histo.c b/lib/isc/histo.c index 395b27b6b6..870c3c0152 100644 --- a/lib/isc/histo.c +++ b/lib/isc/histo.c @@ -27,13 +27,6 @@ #include #include -/* - * XXXFANF to be added to by a commmit in a qp-trie - * feature branch - */ -#define STRUCT_FLEX_SIZE(pointer, member, count) \ - (sizeof(*(pointer)) + sizeof(*(pointer)->member) * (count)) - /* * XXXFANF this should probably be in too */ diff --git a/lib/isc/ht.c b/lib/isc/ht.c index d9de112e54..4d771882dd 100644 --- a/lib/isc/ht.c +++ b/lib/isc/ht.c @@ -287,7 +287,7 @@ isc__ht_add(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize, hash = hash_32(hashval, ht->hashbits[idx]); - node = isc_mem_get(ht->mctx, sizeof(*node) + keysize); + node = isc_mem_get(ht->mctx, STRUCT_FLEX_SIZE(node, key, keysize)); *node = (isc_ht_node_t){ .keysize = keysize, .hashval = hashval, @@ -396,7 +396,7 @@ isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize, prev->next = node->next; } isc_mem_put(ht->mctx, node, - sizeof(*node) + node->keysize); + STRUCT_FLEX_SIZE(node, key, node->keysize)); ht->count--; return (ISC_R_SUCCESS); diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h index 7fe6715a4e..c8b6e1c99f 100644 --- a/lib/isc/include/isc/util.h +++ b/lib/isc/include/isc/util.h @@ -96,6 +96,14 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +/*% + * Get the allocation size for a struct with a flexible array member + * containing `count` elements. The struct is identified by a pointer, + * typically the one that points to (or will point to) the allocation. + */ +#define STRUCT_FLEX_SIZE(pointer, member, count) \ + (sizeof(*(pointer)) + sizeof(*(pointer)->member) * (count)) + /*% * Use this in translation units that would otherwise be empty, to * suppress compiler warnings.