SDL: Fix SDL_BlitSurfaceScaled crash (b1cad)

From b1cadf0e99d0a592b16231524838a20317679fa6 Mon Sep 17 00:00:00 2001
From: capehill <[EMAIL REDACTED]>
Date: Sun, 29 Jun 2025 16:34:05 +0300
Subject: [PATCH] Fix SDL_BlitSurfaceScaled crash

SDL_BlitSurfaceScaled could crash when passed large coordinates, due
to final_dst.w or final_dst.h getting negative values.

(cherry picked from commit 1c5c3b1479a05196bee38aab101c5d3ef4a8c754)
---
 src/video/SDL_surface.c       |  2 +-
 test/testautomation_surface.c | 44 +++++++++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c
index 73049a50bedec..92715d2efc4bd 100644
--- a/src/video/SDL_surface.c
+++ b/src/video/SDL_surface.c
@@ -1247,7 +1247,7 @@ bool SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surfac
     // Clip again
     SDL_GetRectIntersection(clip_rect, &final_dst, &final_dst);
 
-    if (final_dst.w == 0 || final_dst.h == 0 ||
+    if (final_dst.w <= 0 || final_dst.h <= 0 ||
         final_src.w < 0 || final_src.h < 0) {
         // No-op.
         return true;
diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c
index 39135d015a993..2a52fbb4bf5e2 100644
--- a/test/testautomation_surface.c
+++ b/test/testautomation_surface.c
@@ -989,6 +989,45 @@ static int SDLCALL surface_testBlitInvalid(void *arg)
     return TEST_COMPLETED;
 }
 
+static int SDLCALL surface_testBlitsWithBadCoordinates(void *arg)
+{
+    const SDL_Rect rect[8] = {
+        { SDL_MAX_SINT32, 0, 2, 2 },
+        { 0, SDL_MAX_SINT32, 2, 2 },
+        { 0, 0, SDL_MAX_SINT32, 2 },
+        { 0, 0, 2, SDL_MAX_SINT32 },
+        { SDL_MIN_SINT32, 0, 2, 2 },
+        { 0, SDL_MIN_SINT32, 2, 2 },
+        { 0, 0, SDL_MIN_SINT32, 2 },
+        { 0, 0, 2, SDL_MIN_SINT32 }
+    };
+
+    SDL_Surface *s;
+    bool result;
+    int i;
+
+    s = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA8888);
+    SDLTest_AssertCheck(s != NULL, "Check surface creation");
+
+    for (i = 0; i < 8; i++) {
+        result = SDL_BlitSurface(s, NULL, s, &rect[i]);
+        SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, NULL, valid, &rect), result = %s", result ? "true" : "false");
+
+        result = SDL_BlitSurface(s, &rect[i], s, NULL);
+        SDLTest_AssertCheck(result == true, "SDL_BlitSurface(valid, &rect, valid, NULL), result = %s", result ? "true" : "false");
+
+        result = SDL_BlitSurfaceScaled(s, NULL, s, &rect[i], SDL_SCALEMODE_NEAREST);
+        SDLTest_AssertCheck(result == true, "SDL_BlitSurfaceScaled(valid, NULL, valid, &rect, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
+
+        result = SDL_BlitSurfaceScaled(s, &rect[i], s, NULL, SDL_SCALEMODE_NEAREST);
+        SDLTest_AssertCheck(result == true, "SDL_BlitSurfaceScaled(valid, &rect, valid, NULL, SDL_SCALEMODE_NEAREST), result = %s", result ? "true" : "false");
+    }
+
+    SDL_DestroySurface(s);
+
+    return TEST_COMPLETED;
+}
+
 static int SDLCALL surface_testOverflow(void *arg)
 {
     char buf[1024];
@@ -1664,6 +1703,10 @@ static const SDLTest_TestCaseReference surfaceTestBlitInvalid = {
     surface_testBlitInvalid, "surface_testBlitInvalid", "Tests blitting routines with invalid surfaces.", TEST_ENABLED
 };
 
+static const SDLTest_TestCaseReference surfaceTestBlitsWithBadCoordinates = {
+    surface_testBlitsWithBadCoordinates, "surface_testBlitsWithBadCoordinates", "Test blitting routines with bad coordinates.", TEST_ENABLED
+};
+
 static const SDLTest_TestCaseReference surfaceTestOverflow = {
     surface_testOverflow, "surface_testOverflow", "Test overflow detection.", TEST_ENABLED
 };
@@ -1713,6 +1756,7 @@ static const SDLTest_TestCaseReference *surfaceTests[] = {
     &surfaceTestBlitBlendMod,
     &surfaceTestBlitBlendMul,
     &surfaceTestBlitInvalid,
+    &surfaceTestBlitsWithBadCoordinates,
     &surfaceTestOverflow,
     &surfaceTestFlip,
     &surfaceTestPalette,