summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2017-11-27 18:49:02 +0100
committerAnatol Belski <ab@php.net>2017-11-27 18:49:02 +0100
commit2b7d283cc5589077d7ecc23cc9b2827759cab5c2 (patch)
tree9c7875b29f85dc742ee6538c3a58b3276518c21f
parent34b19387c257a32b4d58929ee0632529239e8fa6 (diff)
downloadphp-git-2b7d283cc5589077d7ecc23cc9b2827759cab5c2.tar.gz
Fixed bug #75574 putenv does not work properly if parameter contains non-ASCII unicode character
-rw-r--r--ext/standard/basic_functions.c51
-rw-r--r--ext/standard/tests/general_functions/putenv_bug75574_cp936_win.phpt61
-rw-r--r--ext/standard/tests/general_functions/putenv_bug75574_utf8.phpt50
3 files changed, 153 insertions, 9 deletions
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
@@ -4203,10 +4228,18 @@ PHP_FUNCTION(putenv)
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--
+<?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
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--
+<?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===