SDL: Fixed rare cursor corruption on Windows (05d8a)

From 05d8af1a7561c32059c917c4d7aa8c5f67be6417 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 5 May 2026 08:53:01 -0700
Subject: [PATCH] Fixed rare cursor corruption on Windows

If the cursor was created with a temporary surface that was pointing at external memory, then when the cursor is used it might be referencing memory that had already been freed.

(cherry picked from commit f6f4664ed1c75663e71ab4e39f6de0909fcb5106)
---
 src/video/windows/SDL_windowsmouse.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c
index 2cd4e726f32d2..3e7772b4513f5 100644
--- a/src/video/windows/SDL_windowsmouse.c
+++ b/src/video/windows/SDL_windowsmouse.c
@@ -148,9 +148,23 @@ static SDL_Cursor *WIN_CreateAnimatedCursorAndData(SDL_CursorFrameInfo *frames,
     data->hot_y = hot_y;
     data->num_frames = frame_count;
     for (int i = 0; i < frame_count; ++i) {
-        data->frames[i].surface = frames[i].surface;
+        SDL_Surface *surface = frames[i].surface;
+        if (surface->flags & SDL_SURFACE_PREALLOCATED) {
+            surface = SDL_DuplicateSurface(surface);
+            if (!surface) {
+                while (i > 0) {
+                    --i;
+                    SDL_DestroySurface(data->frames[i].surface);
+                }
+                SDL_free(data);
+                SDL_free(cursor);
+                return NULL;
+            }
+        } else {
+            ++surface->refcount;
+        }
+        data->frames[i].surface = surface;
         data->frames[i].duration = frames[i].duration;
-        ++frames[i].surface->refcount;
     }
     cursor->internal = data;
     return cursor;