SDL: stdlib: fix SDL_strtol of "0" with base 0

From b713e7581b300f25b6356c975178452728185539 Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Mon, 30 Dec 2024 23:23:36 +0100
Subject: [PATCH] stdlib: fix SDL_strtol of "0" with base 0

SDL_strtol("0") skipped the "0" octal prefix
and returned a failure because the remainder of the string was empty.
---
 src/stdlib/SDL_string.c      |  2 +-
 test/testautomation_stdlib.c | 11 +++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c
index ab43c13d3a850..50da685f7eb57 100644
--- a/src/stdlib/SDL_string.c
+++ b/src/stdlib/SDL_string.c
@@ -368,7 +368,7 @@ static size_t SDL_ScanUnsignedLongLongInternal(const char *text, int count, int
             negative = *text == '-';
             ++text;
         }
-        if ((radix == 0 || radix == 16) && *text == '0') {
+        if ((radix == 0 || radix == 16) && *text == '0' && text[1] != '\0') {
             ++text;
             if (*text == 'x' || *text == 'X') {
                 radix = 16;
diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c
index a2ac6719884b7..26317584f19bc 100644
--- a/test/testautomation_stdlib.c
+++ b/test/testautomation_stdlib.c
@@ -1324,6 +1324,9 @@ static int SDLCALL stdlib_strtox(void *arg)
     STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-uvwxyz", 32, -991, 3);
     STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "ZzZzZzZzZzZzZzZzZzZzZzZzZ", 36, ullong_max, 25);
 
+    STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0", 0, 0, 1);
+    STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "0", 10, 0, 1);
+    STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-0", 0, 0, 2);
     STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, "-0", 10, 0, 2);
     STRTOX_TEST_CASE(SDL_strtoull, unsigned long long, FMT_PRILLu, " - 1", 0, 0, 0); // invalid input
 
@@ -1335,6 +1338,10 @@ static int SDLCALL stdlib_strtox(void *arg)
     // Since the CI runs the tests against a variety of targets, this should be fine in practice.
 
     if (sizeof(long) == 4) {
+        STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "0", 0, 0, 1);
+        STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "0", 10, 0, 1);
+        STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "-0", 0, 0, 2);
+        STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "-0", 10, 0, 2);
         STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "2147483647", 10, 2147483647, 10);
         STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "2147483648", 10, 2147483647, 10);
         STRTOX_TEST_CASE(SDL_strtol, long, "%ld", "-2147483648", 10, -2147483647L - 1, 11);
@@ -1347,6 +1354,10 @@ static int SDLCALL stdlib_strtox(void *arg)
     }
 
     if (sizeof(long long) == 8) {
+        STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "0", 0, 0LL, 1);
+        STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "0", 10, 0LL, 1);
+        STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-0", 0, 0LL, 2);
+        STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-0", 10, 0LL, 2);
         STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "9223372036854775807", 10, 9223372036854775807LL, 19);
         STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "9223372036854775808", 10, 9223372036854775807LL, 19);
         STRTOX_TEST_CASE(SDL_strtoll, long long, FMT_PRILLd, "-9223372036854775808", 10, -9223372036854775807LL - 1, 20);