]> granicus.if.org Git - php/commitdiff
Fixed bug #75574 putenv does not work properly if parameter contains non-ASCII unicod...
authorAnatol Belski <ab@php.net>
Mon, 27 Nov 2017 17:49:02 +0000 (18:49 +0100)
committerAnatol Belski <ab@php.net>
Mon, 27 Nov 2017 17:49:02 +0000 (18:49 +0100)
ext/standard/basic_functions.c
ext/standard/tests/general_functions/putenv_bug75574_cp936_win.phpt [new file with mode: 0644]
ext/standard/tests/general_functions/putenv_bug75574_utf8.phpt [new file with mode: 0644]

index ca615c03b90aa3017c3f2e6a7515ca79b3342d1c..9c613a6d570a2ae39cc4d13a2a88b226988a072c 100644 (file)
@@ -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 (file)
index 0000000..eb5187b
--- /dev/null
@@ -0,0 +1,61 @@
+--TEST--
+Bug #75574 putenv does not work properly if parameter contains non-ASCII unicode character, cp936 Windows
+--SKIPIF--
+<?php
+
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+  die("skip Valid only on Windows");
+}
+if (!sapi_windows_cp_set(936)) {
+       die("skip Required CP 936 or compatible");
+}
+
+?>
+--INI--
+internal_encoding=cp936
+--FILE--
+<?php
+/*
+#vim: set fileencoding=cp936
+#vim: set encoding=cp936
+*/
+
+var_dump(putenv('FOO=°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡°¡°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡°¡°¡°¡'), getenv("FOO"));
+
+var_dump(putenv('FOO=°¡a'), getenv("FOO"));
+var_dump(putenv('FOO=°¡a°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡a°¡a'), getenv("FOO"));
+var_dump(putenv('FOO=°¡a°¡a°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡a°¡°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡a°¡°¡°¡'), getenv("FOO"));
+var_dump(putenv('FOO=°¡a°¡°¡°¡°¡'), getenv("FOO"));
+
+?>
+===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 (file)
index 0000000..70f5d08
--- /dev/null
@@ -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--
+<?php
+/*
+#vim: set fileencoding=utf-8
+#vim: set encoding=utf-8
+*/
+
+var_dump(putenv('FOO=啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊啊啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊啊啊啊'), getenv("FOO"));
+
+var_dump(putenv('FOO=啊a'), getenv("FOO"));
+var_dump(putenv('FOO=啊a啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊a啊a'), getenv("FOO"));
+var_dump(putenv('FOO=啊a啊a啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊a啊啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊a啊啊啊'), getenv("FOO"));
+var_dump(putenv('FOO=啊a啊啊啊啊'), getenv("FOO"));
+
+?>
+===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===