SDL: Store the surface properties in the reserved pointer of a surface

From d71454da1703586f2e9377145fba11c35884b976 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 29 Dec 2023 08:17:06 -0800
Subject: [PATCH] Store the surface properties in the reserved pointer of a
 surface

This prevents us from exposing the properties publicly and allows us to repurpose the pointer later if necessary.

Fixes https://github.com/libsdl-org/SDL/issues/8758
---
 include/SDL3/SDL_surface.h |  6 +-----
 src/video/SDL_surface.c    | 16 +++++++++++-----
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/include/SDL3/SDL_surface.h b/include/SDL3/SDL_surface.h
index 37e5b15251d2..8742cd1b7830 100644
--- a/include/SDL3/SDL_surface.h
+++ b/include/SDL3/SDL_surface.h
@@ -104,11 +104,7 @@ typedef struct SDL_Surface
     int pitch;                  /**< Read-only */
     void *pixels;               /**< Read-write */
 
-    /** Application data associated with the surface */
-    union {
-        void *reserved;         /**< For ABI compatibility only, do not use */
-        SDL_PropertiesID props; /**< Read-only */
-    };
+    void *reserved;             /**< Private */
 
     /** information needed for surfaces requiring locks */
     int locked;                 /**< Read-only */
diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c
index b0a57d4e6e5b..dec18df53d8e 100644
--- a/src/video/SDL_surface.c
+++ b/src/video/SDL_surface.c
@@ -252,23 +252,28 @@ SDL_Surface *SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitc
 
 SDL_PropertiesID SDL_GetSurfaceProperties(SDL_Surface *surface)
 {
+    SDL_PropertiesID props;
+
     if (!surface) {
         SDL_InvalidParamError("surface");
         return 0;
     }
 
-    if (!(surface->flags & SDL_SURFACE_USES_PROPERTIES)) {
+    if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
+        props = (SDL_PropertiesID)(uintptr_t)surface->reserved;
+    } else {
         if (surface->reserved != NULL) {
             SDL_SetError("Surface has userdata, incompatible with properties");
             return 0;
         }
 
-        surface->props = SDL_CreateProperties();
-        if (surface->props) {
+        props = SDL_CreateProperties();
+        if (props) {
+            surface->reserved = (void *)(uintptr_t)props;
             surface->flags |= SDL_SURFACE_USES_PROPERTIES;
         }
     }
-    return surface->props;
+    return props;
 }
 
 int SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette)
@@ -1570,7 +1575,8 @@ void SDL_DestroySurface(SDL_Surface *surface)
     }
 
     if (surface->flags & SDL_SURFACE_USES_PROPERTIES) {
-        SDL_DestroyProperties(surface->props);
+        SDL_PropertiesID props = (SDL_PropertiesID)(uintptr_t)surface->reserved;
+        SDL_DestroyProperties(props);
     }
 
     SDL_InvalidateMap(surface->map);