From 87b19b3aba0c8535d48ad07e2dae2e09373c913a Mon Sep 17 00:00:00 2001 From: Ray Molenkamp Date: Fri, 11 Dec 2020 11:59:14 -0700 Subject: Fix: BLI_getenv returns ascii not UTF8 on windows BLI_getenv has always incorrectly returned ascii rather than UTF-8. This change corrects this behaviour. This resolves issues when the `BLENDER_USER_CONFIG` environment variable contains a path with Unicode characters on windows as reported in T74510 (but unlikely the root cause for the issue at hand there) Differential Revision: https://developer.blender.org/D9831 Reviewed by: brecht --- source/blender/blenlib/intern/path_util.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'source/blender/blenlib/intern/path_util.c') diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 74bbe59bc04..461f8a53beb 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -32,6 +32,7 @@ #include "BLI_fnmatch.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" #include "BLI_utildefines.h" #ifdef WIN32 @@ -1307,18 +1308,30 @@ void BLI_setenv_if_new(const char *env, const char *val) * On windows getenv gets its variables from a static copy of the environment variables taken at * process start-up, causing it to not pick up on environment variables created during runtime. * This function uses an alternative method to get environment variables that does pick up on - * runtime environment variables. + * runtime environment variables. The result will be UTF-8 encoded. */ + const char *BLI_getenv(const char *env) { #ifdef _MSC_VER - static char buffer[32767]; /* 32767 is the total size of the environment block on windows*/ - if (GetEnvironmentVariableA(env, buffer, sizeof(buffer))) { - return buffer; - } - else { - return NULL; + const char *result = NULL; + static wchar_t buffer[32768]; /* 32767 is the maximum size of the environment variable on + windows, reserve one more character for the zero terminator. */ + wchar_t *env_16 = alloc_utf16_from_8(env, 0); + if (env_16) { + if (GetEnvironmentVariableW(env_16, buffer, ARRAY_SIZE(buffer))) { + char *res_utf8 = alloc_utf_8_from_16(buffer, 0); + // make sure the result is valid, and will fit into our temporary storage buffer + if (res_utf8 && (strlen(res_utf8) + 1) < sizeof(buffer)) { + // We are re-using the utf16 buffer here, since allocating a second static buffer to + // contain the UTF-8 version to return would be wasteful. + memcpy(buffer, res_utf8, strlen(res_utf8) + 1); + free(res_utf8); + result = (const char *)buffer; + } + } } + return result; #else return getenv(env); #endif -- cgit v1.2.3