From 2b7d283cc5589077d7ecc23cc9b2827759cab5c2 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 27 Nov 2017 18:49:02 +0100 Subject: Fixed bug #75574 putenv does not work properly if parameter contains non-ASCII unicode character --- ext/standard/basic_functions.c | 51 ++++++++++++++---- .../putenv_bug75574_cp936_win.phpt | 61 ++++++++++++++++++++++ .../general_functions/putenv_bug75574_utf8.phpt | 50 ++++++++++++++++++ 3 files changed, 153 insertions(+), 9 deletions(-) create mode 100644 ext/standard/tests/general_functions/putenv_bug75574_cp936_win.phpt create mode 100644 ext/standard/tests/general_functions/putenv_bug75574_utf8.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index ca615c03b9..9c613a6d57 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -4072,14 +4072,20 @@ PHP_FUNCTION(getenv) } #ifdef PHP_WIN32 { - char dummybuf; - int size; + wchar_t dummybuf; + DWORD size; + wchar_t *keyw, *valw; + + keyw = php_win32_cp_conv_any_to_w(str, str_len, PHP_WIN32_CP_IGNORE_LEN_P); + if (!keyw) { + RETURN_FALSE; + } SetLastError(0); /*If the given bugger is not large enough to hold the data, the return value is the buffer size, in characters, required to hold the string and its terminating null character. We use this return value to alloc the final buffer. */ - size = GetEnvironmentVariableA(str, &dummybuf, 0); + size = GetEnvironmentVariableW(keyw, &dummybuf, 0); if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) { /* The environment variable doesn't exist. */ RETURN_FALSE; @@ -4090,15 +4096,19 @@ PHP_FUNCTION(getenv) RETURN_EMPTY_STRING(); } - ptr = emalloc(size); - size = GetEnvironmentVariableA(str, ptr, size); + valw = emalloc(size); + size = GetEnvironmentVariableW(keyw, valw, size); if (size == 0) { /* has been removed between the two calls */ - efree(ptr); + free(keyw); + efree(valw); RETURN_EMPTY_STRING(); } else { + ptr = php_win32_cp_w_to_any(valw); RETVAL_STRING(ptr); - efree(ptr); + free(ptr); + free(keyw); + efree(valw); return; } } @@ -4183,7 +4193,22 @@ PHP_FUNCTION(putenv) # ifndef PHP_WIN32 if (putenv(pe.putenv_string) == 0) { /* success */ # else - error_code = SetEnvironmentVariable(pe.key, value); + wchar_t *keyw, *valw = NULL; + + keyw = php_win32_cp_any_to_w(pe.key); + if (value) { + valw = php_win32_cp_any_to_w(value); + } + /* valw may be NULL, but the failed conversion still needs to be checked. */ + if (!keyw || !valw && value) { + efree(pe.putenv_string); + efree(pe.key); + free(keyw); + free(valw); + RETURN_FALSE; + } + + error_code = SetEnvironmentVariableW(keyw, valw); if (error_code != 0 # ifndef ZTS @@ -4192,7 +4217,7 @@ PHP_FUNCTION(putenv) Obviously the CRT version will be useful more often. But generally, doing both brings us on the safe track at least in NTS build. */ - && _putenv_s(pe.key, value ? value : "") == 0 + && _wputenv_s(keyw, valw ? valw : L"") == 0 # endif ) { /* success */ # endif @@ -4202,11 +4227,19 @@ PHP_FUNCTION(putenv) if (!strncmp(pe.key, "TZ", pe.key_len)) { tzset(); } +#endif +#if defined(PHP_WIN32) + free(keyw); + free(valw); #endif RETURN_TRUE; } else { efree(pe.putenv_string); efree(pe.key); +#if defined(PHP_WIN32) + free(keyw); + free(valw); +#endif RETURN_FALSE; } } diff --git a/ext/standard/tests/general_functions/putenv_bug75574_cp936_win.phpt b/ext/standard/tests/general_functions/putenv_bug75574_cp936_win.phpt new file mode 100644 index 0000000000..eb5187b205 --- /dev/null +++ b/ext/standard/tests/general_functions/putenv_bug75574_cp936_win.phpt @@ -0,0 +1,61 @@ +--TEST-- +Bug #75574 putenv does not work properly if parameter contains non-ASCII unicode character, cp936 Windows +--SKIPIF-- + +--INI-- +internal_encoding=cp936 +--FILE-- + +===DONE=== +--EXPECTF-- +bool(true) +string(2) "°¡" +bool(true) +string(4) "°¡°¡" +bool(true) +string(6) "°¡°¡°¡" +bool(true) +string(8) "°¡°¡°¡°¡" +bool(true) +string(3) "°¡a" +bool(true) +string(5) "°¡a°¡" +bool(true) +string(6) "°¡a°¡a" +bool(true) +string(8) "°¡a°¡a°¡" +bool(true) +string(7) "°¡a°¡°¡" +bool(true) +string(9) "°¡a°¡°¡°¡" +bool(true) +string(11) "°¡a°¡°¡°¡°¡" +===DONE=== diff --git a/ext/standard/tests/general_functions/putenv_bug75574_utf8.phpt b/ext/standard/tests/general_functions/putenv_bug75574_utf8.phpt new file mode 100644 index 0000000000..70f5d08cea --- /dev/null +++ b/ext/standard/tests/general_functions/putenv_bug75574_utf8.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #75574 putenv does not work properly if parameter contains non-ASCII unicode character, UTF-8 +--INI-- +internal_encoding=utf-8 +--FILE-- + +===DONE=== +--EXPECTF-- +bool(true) +string(3) "å•Š" +bool(true) +string(6) "å•Šå•Š" +bool(true) +string(9) "å•Šå•Šå•Š" +bool(true) +string(12) "å•Šå•Šå•Šå•Š" +bool(true) +string(4) "å•Ša" +bool(true) +string(7) "å•Šaå•Š" +bool(true) +string(8) "å•Šaå•Ša" +bool(true) +string(11) "å•Šaå•Šaå•Š" +bool(true) +string(10) "å•Šaå•Šå•Š" +bool(true) +string(13) "å•Šaå•Šå•Šå•Š" +bool(true) +string(16) "å•Šaå•Šå•Šå•Šå•Š" +===DONE=== -- cgit v1.2.1