From b290793b78141d0131ff135d47cec0c095b807db Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 11 Jul 2026 23:53:08 -0400 Subject: [PATCH] stdinc: On Windows, uppercase the system environment table's var names. Fixes #15086. --- include/SDL3/SDL_stdinc.h | 14 +++++++++++++- src/stdlib/SDL_getenv.c | 12 ++++++++++++ test/testprocess.c | 8 ++++---- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h index 22dbafb566..6901ba59de 100644 --- a/include/SDL3/SDL_stdinc.h +++ b/include/SDL3/SDL_stdinc.h @@ -1776,6 +1776,12 @@ typedef struct SDL_Environment SDL_Environment; * SDL_setenv_unsafe() or SDL_unsetenv_unsafe() if you want changes to persist * in the C runtime environment after SDL_Quit(). * + * Note that on Windows, the variable names pulled in from the system at + * startup have their ASCII values uppercased, to match what most platforms + * expect even though the Windows system environment table is + * case-insensitive. Once those uppercased variable names are in an + * SDL_Environment, SDL treats them as case-sensitive. + * * \returns a pointer to the environment for the process or NULL on failure; * call SDL_GetError() for more information. * @@ -1791,7 +1797,13 @@ typedef struct SDL_Environment SDL_Environment; extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_GetEnvironment(void); /** - * Create a set of environment variables + * Create a set of environment variables. + * + * Note that on Windows, the variable names pulled in from the system, if + * `populated` is true, have their ASCII values uppercased, to match what most + * platforms expect even though the Windows system environment table is + * case-insensitive. Once those uppercased variable names are in an + * SDL_Environment, SDL treats them as case-sensitive. * * \param populated true to initialize it from the C runtime environment, * false to create an empty environment. diff --git a/src/stdlib/SDL_getenv.c b/src/stdlib/SDL_getenv.c index e058c0c90d..ff32f632ae 100644 --- a/src/stdlib/SDL_getenv.c +++ b/src/stdlib/SDL_getenv.c @@ -119,6 +119,11 @@ SDL_Environment *SDL_CreateEnvironment(bool populated) } *value++ = '\0'; + // uppercase ASCII chars in environment variable names on Windows, since the system environment table is case-insensitive. + for (char *ptr = variable; *ptr; ptr++) { + *ptr = (char) SDL_toupper((int) *ptr); // the only UTF-8 bytes that don't have the high-bit set are single-byte ASCII chars, so SDL_toupper will leave multichar stuff alone. + } + SDL_InsertIntoHashTable(env->strings, variable, value, true); } FreeEnvironmentStringsW(strings); @@ -143,6 +148,13 @@ SDL_Environment *SDL_CreateEnvironment(bool populated) } *value++ = '\0'; +#ifdef SDL_PLATFORM_CYGWIN + // uppercase ASCII chars in environment variable names on Windows, since the system environment table is case-insensitive. + for (char *ptr = variable; *ptr; ptr++) { + *ptr = (char) SDL_toupper((int) *ptr); // the only UTF-8 bytes that don't have the high-bit set are single-byte ASCII chars, so SDL_toupper will leave multichar stuff alone. + } +#endif + SDL_InsertIntoHashTable(env->strings, variable, value, true); } } diff --git a/test/testprocess.c b/test/testprocess.c index 2d8f569099..6721e2015c 100644 --- a/test/testprocess.c +++ b/test/testprocess.c @@ -197,8 +197,8 @@ static int SDLCALL process_testInheritedEnv(void *arg) int exit_code; char random_env1[64]; char random_env2[64]; - static const char *const TEST_ENV_KEY1 = "testprocess_inherited_var"; - static const char *const TEST_ENV_KEY2 = "testprocess_other_var"; + static const char *const TEST_ENV_KEY1 = "TESTPROCESS_INHERITED_VAR"; + static const char *const TEST_ENV_KEY2 = "TESTPROCESS_OTHER_VAR"; char *test_env_val1 = NULL; char *test_env_val2 = NULL; char *buffer = NULL; @@ -269,8 +269,8 @@ static int SDLCALL process_testNewEnv(void *arg) int exit_code; char random_env1[64]; char random_env2[64]; - static const char *const TEST_ENV_KEY1 = "testprocess_inherited_var"; - static const char *const TEST_ENV_KEY2 = "testprocess_other_var"; + static const char *const TEST_ENV_KEY1 = "TESTPROCESS_INHERITED_VAR"; + static const char *const TEST_ENV_KEY2 = "TESTPROCESS_OTHER_VAR"; char *test_env_val1 = NULL; char *test_env_val2 = NULL; char *buffer = NULL;