SDL: Fixed allocation and alignment of raw input buffers

From 2b369a14abc2fd065a91a71cb0cb1830a231a9e9 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 2 Jan 2024 09:25:28 -0800
Subject: [PATCH] Fixed allocation and alignment of raw input buffers

---
 src/video/windows/SDL_windowsevents.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index 7d71980267e0..c0a1e4d41e85 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -607,6 +607,26 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, RAWM
     WIN_CheckRawMouseButtons(timestamp, rawmouse->usButtonFlags, data, mouseID);
 }
 
+/* The layout of memory for data returned from GetRawInputBuffer(), documented here:
+ * https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputbuffer
+ */
+typedef struct
+{
+    union
+    {
+        RAWINPUTHEADER header;
+        BYTE padding[24];
+    } hdr;
+
+    union
+    {
+        RAWMOUSE mouse;
+        RAWKEYBOARD keyboard;
+        RAWHID hid;
+    } data;
+
+} ALIGNED_RAWINPUT;
+
 static void WIN_PollRawMouseInput()
 {
     SDL_Mouse *mouse = SDL_GetMouse();
@@ -641,7 +661,7 @@ static void WIN_PollRawMouseInput()
     for (;;) {
         if (total == data->rawinput_count) {
             count = total + 8;
-            input = (RAWINPUT *)SDL_malloc(count * data->rawinput_size);
+            input = (RAWINPUT *)SDL_realloc(data->rawinput, count * data->rawinput_size);
             if (!input) {
                 return;
             }
@@ -650,7 +670,7 @@ static void WIN_PollRawMouseInput()
         }
 
         size = (data->rawinput_count - total) * data->rawinput_size;
-        count = GetRawInputBuffer(&data->rawinput[total], &size, sizeof(RAWINPUTHEADER));
+        count = GetRawInputBuffer((RAWINPUT *)((BYTE *)data->rawinput + (total * data->rawinput_size)), &size, sizeof(RAWINPUTHEADER));
         if (count == (UINT)-1 || count == 0) {
             break;
         }
@@ -665,7 +685,7 @@ static void WIN_PollRawMouseInput()
         for (i = 0, input = data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) {
             timestamp += increment;
             if (input->header.dwType == RIM_TYPEMOUSE) {
-                RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + 24);
+                RAWMOUSE *rawmouse = &(((ALIGNED_RAWINPUT *)input)->data.mouse);
                 WIN_HandleRawMouseInput(timestamp, window->driverdata, rawmouse);
             }
         }