Skip to content

Commit faf5160

Browse files
committed
fix(platform): read environment variables wide on Windows
Layer 2 of DeusData#996, forced by the new guard going RED on the Windows CI leg with the writer fix alone: _environ holds ANSI-code-page bytes, not UTF-8, so a non-ASCII USERPROFILE or CBM_CACHE_DIR arrives either mojibake'd or with unrepresentable characters replaced by '?' - which is invalid in Windows paths, so every downstream wide-safe file API fails no matter how correct it is. cbm_safe_getenv now reads the value via GetEnvironmentVariableW and converts to genuine UTF-8 (cbm_wide_to_utf8), matching the UTF-8-path convention the rest of the codebase assumes; missing variables honor the fallback as before, and conversion trouble falls back to the ANSI scan rather than failing. POSIX untouched. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
1 parent d9adfeb commit faf5160

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

‎src/foundation/platform.c‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,42 @@ extern char **environ;
304304
#endif
305305

306306
const char *cbm_safe_getenv(const char *name, char *buf, size_t buf_sz, const char *fallback) {
307+
#ifdef _WIN32
308+
/* #996 Layer 2: _environ holds ANSI-code-page bytes, NOT UTF-8. A
309+
* non-ASCII value (USERPROFILE of C:\Users\Kovács János, or a Greek/CJK
310+
* CBM_CACHE_DIR) arrives here either mojibake'd or with unrepresentable
311+
* characters replaced by '?', which is INVALID in Windows paths — every
312+
* downstream wide-safe file API then fails no matter how correct it is.
313+
* Read the value wide and convert to genuine UTF-8, matching the
314+
* UTF-8-path convention the rest of the codebase (cbm_fopen, _wmkdir,
315+
* SQLite VFS) already assumes. */
316+
{
317+
wchar_t wname[CBM_SZ_256];
318+
int wn = MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, CBM_SZ_256);
319+
if (wn > 0) {
320+
wchar_t wval[CBM_SZ_2K];
321+
DWORD got = GetEnvironmentVariableW(wname, wval, CBM_SZ_2K);
322+
if (got > 0 && got < CBM_SZ_2K) {
323+
char *utf8 = cbm_wide_to_utf8(wval);
324+
if (utf8) {
325+
snprintf(buf, buf_sz, "%s", utf8);
326+
free(utf8);
327+
return buf;
328+
}
329+
}
330+
if (got == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
331+
if (fallback) {
332+
snprintf(buf, buf_sz, "%s", fallback);
333+
return buf;
334+
}
335+
buf[0] = '\0';
336+
return NULL;
337+
}
338+
}
339+
/* Conversion trouble (oversized value, allocation) — fall through to
340+
* the ANSI scan below rather than failing outright. */
341+
}
342+
#endif
307343
char **env = CBM_ENVIRON;
308344
if (env) {
309345
size_t nlen = strlen(name);

0 commit comments

Comments
 (0)