From 61bc856b043fedafa542a1a44dfc4e9af630f1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20=C3=85stholm?= Date: Thu, 12 Sep 2024 00:26:36 +0200 Subject: [PATCH] stdlib: Use new parser for scanf %p specifier --- src/stdlib/SDL_string.c | 45 +++++++++++++----------------------- test/testautomation_stdlib.c | 10 ++++++++ 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c index 75239d7726..355fce16f8 100644 --- a/src/stdlib/SDL_string.c +++ b/src/stdlib/SDL_string.c @@ -305,11 +305,6 @@ static Uint32 StepUTF32(const Uint32 **_str, const size_t slen) } #endif -#if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOL) || !defined(HAVE_WCSTOL) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD) || !defined(HAVE_STRTOLL) || !defined(HAVE_STRTOULL) -#define SDL_isupperhex(X) (((X) >= 'A') && ((X) <= 'F')) -#define SDL_islowerhex(X) (((X) >= 'a') && ((X) <= 'f')) -#endif - #define UTF8_IsLeadByte(c) ((c) >= 0xC0 && (c) <= 0xF4) #define UTF8_IsTrailingByte(c) ((c) >= 0x80 && (c) <= 0xBF) @@ -534,33 +529,25 @@ static size_t SDL_ScanUnsignedLong(const char *text, int count, int radix, unsig #endif #ifndef HAVE_VSSCANF -static size_t SDL_ScanUintPtrT(const char *text, int radix, uintptr_t *valuep) +static size_t SDL_ScanUintPtrT(const char *text, uintptr_t *valuep) { - const char *textstart = text; - uintptr_t value = 0; - - if (radix == 16 && SDL_strncmp(text, "0x", 2) == 0) { - text += 2; - } - for (;;) { - int v; - if (SDL_isdigit((unsigned char)*text)) { - v = *text - '0'; - } else if (radix == 16 && SDL_isupperhex(*text)) { - v = 10 + (*text - 'A'); - } else if (radix == 16 && SDL_islowerhex(*text)) { - v = 10 + (*text - 'a'); + const uintptr_t uintptr_max = ~(uintptr_t)0; + unsigned long long value; + bool negative; + size_t len = SDL_ScanUnsignedLongLongInternal(text, 0, 16, &value, &negative); + if (negative) { + if (value == 0 || value > uintptr_max) { + value = uintptr_max; + } else if (value == uintptr_max) { + value = 1; } else { - break; + value = 0ULL - value; } - value *= radix; - value += v; - ++text; + } else if (value > uintptr_max) { + value = uintptr_max; } - if (valuep && text > textstart) { - *valuep = value; - } - return text - textstart; + *valuep = value; + return len; } #endif @@ -1616,7 +1603,7 @@ int SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_li case 'p': { uintptr_t value = 0; - advance = SDL_ScanUintPtrT(text, 16, &value); + advance = SDL_ScanUintPtrT(text, &value); text += advance; if (advance && !suppress) { void **valuep = va_arg(ap, void **); diff --git a/test/testautomation_stdlib.c b/test/testautomation_stdlib.c index 0f5f5bd60d..28d19750b7 100644 --- a/test/testautomation_stdlib.c +++ b/test/testautomation_stdlib.c @@ -726,6 +726,7 @@ static int SDLCALL stdlib_sscanf(void *arg) long long_output, expected_long_output; long long long_long_output, expected_long_long_output; size_t size_output, expected_size_output; + uintptr_t uintptr_output, expected_uintptr_output; char text[128], text2[128]; expected_output = output = 123; @@ -790,6 +791,15 @@ static int SDLCALL stdlib_sscanf(void *arg) SDLTest_AssertCheck(expected_size_output == size_output, "Check output, expected: %zu, got: %zu", expected_size_output, size_output); SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + uintptr_output = 123; + expected_uintptr_output = 0x1234567; + expected_result = 1; + result = SDL_snprintf(text, sizeof(text), "%p", expected_uintptr_output); + result = SDL_sscanf(text, "%p", &uintptr_output); + SDLTest_AssertPass("Call to SDL_sscanf(\"%s\", \"%%p\", &output)", text); + SDLTest_AssertCheck(expected_uintptr_output == uintptr_output, "Check output, expected: %p, got: %p", expected_uintptr_output, uintptr_output); + SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result); + expected_result = 1; text[0] = '\0'; result = SDL_sscanf("abc def", "%s", text);