aboutsummaryrefslogtreecommitdiffstats
path: root/hash.c
diff options
context:
space:
mode:
authorLars Kanis <kanis@comcard.de>2020-12-07 18:00:39 +0100
committerGitHub <noreply@github.com>2020-12-08 02:00:39 +0900
commitca76337a00244635faa331afd04f4b75161ce6fb (patch)
tree7fae6bdb4c21e81656b2c6399c26752f075bcce5 /hash.c
parent94b6933d1c6f4c8698319fbcac9dcecc9033b4b9 (diff)
downloadruby-ca76337a00244635faa331afd04f4b75161ce6fb.tar.gz
Windows: Read ENV names and values as UTF-8 encoded Strings (#3818)
* Windows: Read ENV names and values as UTF-8 encoded Strings Implements issue #12650: fix https://bugs.ruby-lang.org/issues/12650 This also removes the special encoding for ENV['PATH'] and some complexity in the code that is unnecessary now. * Windows: Improve readablity of getenv() encoding getenv() did use the expected codepage as an implicit parameter of the macro. This is mis-leading since include/ruby/win32.h has a different definition. Using the "cp" variable explicit (like the other function calls) makes it more readable and consistent. * Windows: Change external C-API macros getenv() and execv() to use UTF-8 They used to process and return strings with locale encoding, but since all ruby-internal spawn and environment functions use UTF-8, it makes sense to change the C-API equally.
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c75
1 files changed, 13 insertions, 62 deletions
diff --git a/hash.c b/hash.c
index bde35d06b0..98405ec541 100644
--- a/hash.c
+++ b/hash.c
@@ -4815,22 +4815,7 @@ static char **my_environ;
#undef environ
#define environ my_environ
#undef getenv
-static char *(*w32_getenv)(const char*);
-static char *
-w32_getenv_unknown(const char *name)
-{
- char *(*func)(const char*);
- if (rb_locale_encindex() == rb_ascii8bit_encindex()) {
- func = rb_w32_getenv;
- }
- else {
- func = rb_w32_ugetenv;
- }
- /* atomic assignment in flat memory model */
- return (w32_getenv = func)(name);
-}
-static char *(*w32_getenv)(const char*) = w32_getenv_unknown;
-#define getenv(n) w32_getenv(n)
+#define getenv(n) rb_w32_ugetenv(n)
#elif defined(__APPLE__)
#undef environ
#define environ (*_NSGetEnviron())
@@ -4849,20 +4834,20 @@ extern char **environ;
#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
#endif
-static VALUE
-env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
+static inline rb_encoding *
+env_encoding()
{
#ifdef _WIN32
- rb_encoding *internal = rb_default_internal_encoding();
- const int ecflags = ECONV_INVALID_REPLACE | ECONV_UNDEF_REPLACE;
- rb_encoding *utf8 = rb_utf8_encoding();
- VALUE str = rb_enc_str_new(NULL, 0, (internal ? internal : enc));
- if (NIL_P(rb_str_cat_conv_enc_opts(str, 0, ptr, len, utf8, ecflags, Qnil))) {
- rb_str_initialize(str, ptr, len, NULL);
- }
+ return rb_utf8_encoding();
#else
- VALUE str = rb_external_str_new_with_enc(ptr, len, enc);
+ return rb_locale_encoding();
#endif
+}
+
+static VALUE
+env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
+{
+ VALUE str = rb_external_str_new_with_enc(ptr, len, enc);
rb_obj_freeze(str);
return str;
@@ -4877,7 +4862,7 @@ env_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
static VALUE
env_str_new(const char *ptr, long len)
{
- return env_enc_str_new(ptr, len, rb_locale_encoding());
+ return env_enc_str_new(ptr, len, env_encoding());
}
static VALUE
@@ -4889,46 +4874,23 @@ env_str_new2(const char *ptr)
static const char TZ_ENV[] = "TZ";
-static rb_encoding *
-env_encoding_for(const char *name, const char *ptr)
-{
- if (ENVMATCH(name, PATH_ENV)) {
- return rb_filesystem_encoding();
- }
- else {
- return rb_locale_encoding();
- }
-}
-
static VALUE
env_name_new(const char *name, const char *ptr)
{
- return env_enc_str_new_cstr(ptr, env_encoding_for(name, ptr));
+ return env_enc_str_new_cstr(ptr, env_encoding());
}
static void *
get_env_cstr(
-#ifdef _WIN32
- volatile VALUE *pstr,
-#else
VALUE str,
-#endif
const char *name)
{
-#ifdef _WIN32
- VALUE str = *pstr;
-#endif
char *var;
rb_encoding *enc = rb_enc_get(str);
if (!rb_enc_asciicompat(enc)) {
rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s",
name, rb_enc_name(enc));
}
-#ifdef _WIN32
- if (!rb_enc_str_asciionly_p(str)) {
- *pstr = str = rb_str_conv_enc(str, NULL, rb_utf8_encoding());
- }
-#endif
var = RSTRING_PTR(str);
if (memchr(var, '\0', RSTRING_LEN(str))) {
rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name);
@@ -4936,13 +4898,8 @@ get_env_cstr(
return rb_str_fill_terminator(str, 1); /* ASCII compatible */
}
-#ifdef _WIN32
-#define get_env_ptr(var, val) \
- (var = get_env_cstr(&(val), #var))
-#else
#define get_env_ptr(var, val) \
(var = get_env_cstr(val, #var))
-#endif
static inline const char *
env_name(volatile VALUE *s)
@@ -4983,9 +4940,6 @@ env_delete(VALUE name)
VALUE value = env_str_new2(val);
ruby_setenv(nam, 0);
- if (ENVMATCH(nam, PATH_ENV)) {
- RB_GC_GUARD(name);
- }
return value;
}
return Qnil;
@@ -5407,9 +5361,6 @@ env_aset(VALUE nm, VALUE val)
get_env_ptr(value, val);
ruby_setenv(name, value);
- if (ENVMATCH(name, PATH_ENV)) {
- RB_GC_GUARD(nm);
- }
reset_by_modified_env(name);
return val;
}