From 143130066be214280a3c6d4abc4cfe97c10a5f6f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 13 Oct 2020 09:34:04 +0200 Subject: [PATCH] c-rbtree: fix struct alignment of CRBTree on m68k architectures On m68k, 32bit integer are aligned to only 2 bytes. This breaks assumptions and a static assertion of c-rbtree. Explicitly require that the first field is aligned to at least 4 bytes. This fixes the build and ensures that all valid pointers to a CRBTree have the lowest two bits unset (so they can be used for storing 2 additional flags). Use a union instead of aligning __parent_and_flags itself. That is because alignas() cannot lower the natural alignment, so if we would want to align __parent_and_flags, we could only do alignas(sizeof(unsigned long) > 4 ? sizeof(unsigned long) : 4) That would not be correct if "long" is 8 bytes long but had a natural alignment of only 4. The union allows us to specify an alignment of at least 4, but otherwise follow natural alignment. https://github.com/c-util/c-rbtree/commit/10d973a9e6718516a6839c8b87a3e630c5391d53 --- shared/c-rbtree/src/c-rbtree.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shared/c-rbtree/src/c-rbtree.h b/shared/c-rbtree/src/c-rbtree.h index a9bbce52f2..d1941185fb 100644 --- a/shared/c-rbtree/src/c-rbtree.h +++ b/shared/c-rbtree/src/c-rbtree.h @@ -27,6 +27,7 @@ extern "C" { #endif #include +#include #include typedef struct CRBNode CRBNode; @@ -58,7 +59,10 @@ typedef struct CRBTree CRBTree; * C_RBNODE_INIT. */ struct CRBNode { - unsigned long __parent_and_flags; + union { + unsigned long __parent_and_flags; + alignas(4) char __dmmy_for_struct_alignment; + }; CRBNode *left; CRBNode *right; };