From 00365a7beb45d5c87823434d65004a5a84c197fe Mon Sep 17 00:00:00 2001 From: Maarten Boot <11140490+maarten-boot@users.noreply.github.com> Date: Tue, 3 Nov 2026 09:24:02 +0100 Subject: [PATCH] ass: keep the areas of its allocator aligned for the host getarea() rounds sizes to sizeof(int) and splits free blocks from the end, so after a name (strlen + 1 bytes) the next area is at 4 (mod 8), and the structs kept there (line_t, relc_t, locl_t, stat_t and the allocator's own freeblock, all with pointers) are misaligned on a 64-bit host: -fsanitize=alignment reports 919 accesses in em_ass when the em22 examples are linked. Round all sizes to _Alignof(max_align_t), and to at least the size of a free block's header, as led does since its alignment fix; align the workspace in main()'s frame that is given to the allocator at start. em_ass's output is unchanged (the seven em22 examples are identical). Co-Authored-By: Claude Opus 5.5 --- util/ass/ass00.c | 3 ++- util/ass/asscm.c | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/util/ass/ass00.c b/util/ass/ass00.c index 3a0500748..faa0e2c7b 100644 --- a/util/ass/ass00.c +++ b/util/ass/ass00.c @@ -48,7 +48,8 @@ int main(int argc, char** argv) * The d flag can be repeated several times, resulting in more * debugging information. */ - char workspace[6000]; + /* Given to the allocator (asscm.c): aligned as its areas must be. */ + _Alignas(max_align_t) char workspace[6000]; char* cp; int argno; diff --git a/util/ass/asscm.c b/util/ass/asscm.c index c6886a3fd..42603961f 100644 --- a/util/ass/asscm.c +++ b/util/ass/asscm.c @@ -18,6 +18,7 @@ The algorithm is first fit. */ +#include #include #include #include "ass00.h" @@ -41,13 +42,29 @@ static struct freeblock freexx[2] = { { freexx, 0 }, { freexx + 1, 0 } }; #define CHUNK 2048 /* Smallest chunk to be gotten from UNIX */ +/* + * Every area and every free block starts at a multiple of ALIGN, so that + * the structs kept in them (line_t, relc_t, locl_t, ... with pointers: 8 + * bytes on a 64-bit host) are aligned: malloc() returns such addresses, + * and all sizes are rounded up to ALIGN. A free block must also have room + * for its own header. + */ +#define ALIGN _Alignof(max_align_t) + +static unsigned int roundsize(unsigned int size) +{ + if (size < sizeof(struct freeblock)) + size = sizeof(struct freeblock); + return (size + (ALIGN - 1)) & ~(unsigned int)(ALIGN - 1); +} + area_t getarea(unsigned int size) { struct freeblock *c_ptr, *l_ptr; char* ptr; unsigned rqsize; - size = ((size + (sizeof(int) - 1)) / sizeof(int)) * sizeof(int); + size = roundsize(size); #ifdef MEMUSE m_used += size; m_free -= size; @@ -75,7 +92,7 @@ area_t getarea(unsigned int size) if (ptr) break; /* request succesfull */ rqsize /= 2; - rqsize -= rqsize % sizeof(int); + rqsize -= rqsize % ALIGN; if (rqsize < sizeof freehead) { fatal("Out of memory"); @@ -93,7 +110,7 @@ void freearea(area_t ptr, unsigned int size) { struct freeblock *c_ptr, *l_ptr; - size = ((size + (sizeof(int) - 1)) / sizeof(int)) * sizeof(int); + size = roundsize(size); #ifdef MEMUSE m_free += size; m_used -= size;