SDL: Don't pack SDL_AudioCVT on CHERI architectures

From e4411505ab139b9b9aeba65b93c64551b2478291 Mon Sep 17 00:00:00 2001
From: Jessica Clarke <[EMAIL REDACTED]>
Date: Thu, 29 Jul 2021 19:04:39 +0100
Subject: [PATCH] Don't pack SDL_AudioCVT on CHERI architectures

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.

The referential safety is enforced through the use of tagged memory, and
there is only a single tag bit per capability-sized word, meaning it is
impossible to store capabilities at unaligned locations, either getting
a trap on load/store or the validity tag being stripped when
round-tripepd through memory.

Since this is a new ABI for which SDL has never been compiled before, we
do not need to be concerned with this compatibility measure, so just
don't pack the struct for CHERI architectures.

This code is inherently rather dubious anyway; if MSVC and GCC disagree
on struct layout when targeting Windows then that is a bug in GCC, but
likely extends from the bogus #pragma pack directives for MSVC in
begin_code.h, which will force types to be *underaligned* (and is
attempting to work around something that is fundamentally a broken idea
to be doing). In particular 8-byte-aligned types will be underaligned to
4 bytes, but only on MSVC.  Since that code is not used for GCC that is
probably the cause of the struct layout discrepancy, and there are
likely other instances of that throughout SDL. Moreover, the supposed
fix here is not in fact a fix, as now GCC will think SDL_AudioCVT is
only 1-byte-aligned but MSVC will think it's 4-byte or 8-byte-aligned,
meaning ABI incomatibility is introduced by this change. However,
removing it would break ABI compatibility for purely-GCC-compiled code
(as old binaries would see the struct as 1-byte-aligned and new binaries
would see the struct as 8-byte-aligned) so SDL is stuck with this until
it bumps its ABI.
 include/SDL_audio.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/SDL_audio.h b/include/SDL_audio.h
index 05b482b023..39ebe0e187 100644
--- a/include/SDL_audio.h
+++ b/include/SDL_audio.h
@@ -214,9 +214,12 @@ typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
  *  set both its (buf) field to a pointer that is aligned to 16 bytes, and its
  *  (len) field to something that's a multiple of 16, if possible.
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__)
 /* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
    pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+   This is not a concern on CHERI architectures, where pointers must be stored
+   at aligned locations otherwise they will become invalid, and thus structs
+   containing pointers cannot be packed without giving a warning or error.
    The next time we rev the ABI, make sure to size the ints and add padding.