SDL: Fix pointer provenance in SDL_SIMDRealloc

From 02daab8736e80ce0e48d91ca82954067be5c79a5 Mon Sep 17 00:00:00 2001
From: Jessica Clarke <[EMAIL REDACTED]>
Date: Thu, 29 Jul 2021 18:09:38 +0100
Subject: [PATCH] Fix pointer provenance in SDL_SIMDRealloc

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 C standard does not guarantee that if two pointers compare equal
they are the same pointer, as C pointers have a notion of provenance,
and compilers have been known to exploit this during optimisation. For
CHERI, this becomes even more important, as in-place expansion can
result in realloc returning a capability to the same address but with
increased capability bounds, and so reusing the old capability will trap
trying to access outside the bounds of the original allocation.

In the case that ptr == mem, memdiff and ptrdiff should still be equal,
so the only overhead is a small amount of pointer arithmetic and a store
of the new pointer (which is required per the C standard in order to not
be undefined behaviour when next loaded).

This also fixes the calculation of oldmem to use uintptr_t rather than
size_t as casting the pointer to size_t on CHERI will strip the
capability metadata, including the validity tag, with the subsequent
cast back to void * resulting in a null-derived capability whose
validity tag is clear and thus cannot be dereferenced without trapping.
 src/cpuinfo/SDL_cpuinfo.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c
index 9d602cf196..ded6cd5e52 100644
--- a/src/cpuinfo/SDL_cpuinfo.c
+++ b/src/cpuinfo/SDL_cpuinfo.c
@@ -1087,9 +1087,6 @@ SDL_SIMDRealloc(void *mem, const size_t len)
     ptr = (Uint8 *) SDL_realloc(mem, padded + alignment + sizeof (void *));
-    if (ptr == mem) {
-        return retval; /* Pointer didn't change, nothing to do */
-    }
     if (ptr == NULL) {
         return NULL; /* Out of memory, bail! */
@@ -1102,7 +1099,7 @@ SDL_SIMDRealloc(void *mem, const size_t len)
     if (mem) {
         ptrdiff = ((size_t) retval) - ((size_t) ptr);
         if (memdiff != ptrdiff) { /* Delta has changed, copy to new offset! */
-            oldmem = (void*) (((size_t) ptr) + memdiff);
+            oldmem = (void*) (((uintptr_t) ptr) + memdiff);
             /* Even though the data past the old `len` is undefined, this is the
              * only length value we have, and it guarantees that we copy all the