From 8afddc966dcf249fb7ed7c60f6518374f3af28e5 Mon Sep 17 00:00:00 2001
From: Jessica Clarke <jrtc27@jrtc27.com>
Date: Fri, 12 Aug 2022 19:57:59 +0100
Subject: [PATCH 3/8] tclInt: Fix TCL_ALIGN for CHERI by not hard-coding 8-byte
 alignment

This is needed to support CHERI, and thus Arm's experimental Morello
prototype, where pointers are implemented using unforgeable capabilities
that include bounds and permissions metadata to provide fine-grained
spatial and referential memory safety, as well as revocation by sweeping
memory to provide heap temporal memory safety.

These capabilities are twice the size of an integer address, or 16 bytes
on a 64-bit system, and require that same alignment, so 8 bytes is not
sufficient. Adjust the definition of TCL_ALIGN to compute the maximum
alignment needed for long long, double and void *, which should be
sufficient for Tcl's purposes. For backwards compatibility, in case
anything is relying on a minimum of 8-byte alignment (since this is an
exported interface), clamp this to a minimum of 8 so that this change
only affects architectures that require even greater alignment.
---
 generic/tclInt.h | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/generic/tclInt.h b/generic/tclInt.h
index 991eee476..dc7554c5f 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -2319,22 +2319,36 @@ typedef struct Interp {
 #endif
 
 /*
- * This macro is used to determine the offset needed to safely allocate any
+ * TCL_ALIGN is used to determine the offset needed to safely allocate any
  * data structure in memory. Given a starting offset or size, it "rounds up"
- * or "aligns" the offset to the next 8-byte boundary so that any data
- * structure can be placed at the resulting offset without fear of an
- * alignment error.
+ * or "aligns" the offset to the next aligned (typically 8-byte) boundary so
+ * that any data structure can be placed at the resulting offset without fear
+ * of an alignment error. Note this is clamped to a minimum of 8 for API
+ * compatibility.
  *
  * WARNING!! DO NOT USE THIS MACRO TO ALIGN POINTERS: it will produce the
- * wrong result on platforms that allocate addresses that are divisible by 4
- * or 2. Only use it for offsets or sizes.
+ * wrong result on platforms that allocate addresses that are divisible by a
+ * non-trivial factor of this alignment. Only use it for offsets or sizes.
  *
  * This macro is only used by tclCompile.c in the core (Bug 926445). It
  * however not be made file static, as extensions that touch bytecodes
  * (notably tbcload) require it.
  */
 
-#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)
+struct Tcl_MaxAlignment {
+    char unalign;
+    union {
+	long long maxAlignLongLong;
+	double maxAlignDouble;
+	void *maxAlignPointer;
+    } aligned;
+};
+#define TCL_ALIGN_BYTES \
+	offsetof(struct Tcl_MaxAlignment, aligned) < 8 \
+	    ? 8 \
+	    : offsetof(struct Tcl_MaxAlignment, aligned)
+#define TCL_ALIGN(x) \
+	(((int)(x) + (TCL_ALIGN_BYTES - 1)) & ~(TCL_ALIGN_BYTES - 1))
 
 /*
  * A common panic alert when memory allocation fails.
-- 
2.34.GIT

