Skip to content

Windows: Read ENV names and values as UTF-8 encoded Strings#3818

Merged
nurse merged 3 commits into
ruby:masterfrom
larskanis:env-utf8
Dec 7, 2020
Merged

Windows: Read ENV names and values as UTF-8 encoded Strings#3818
nurse merged 3 commits into
ruby:masterfrom
larskanis:env-utf8

Conversation

@larskanis

@larskanis larskanis commented Nov 26, 2020

Copy link
Copy Markdown
Contributor

This implements redmine issue 12650, which was postponed to ruby-3.0, but isn't solved so far.

I splitted the PR into 3 commits, which are not necessary related. Please tell me, if I should open 3 separate PRs.

0c6c879: Read ENV names and values as UTF-8 encoded Strings

Implements issue #12650: 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.

9532666: 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.

26ffdf0: 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.

I'm uncertain if this commit is desired, since it changes the C-API, so that getenv() and execv() might not be fully compatible to getenv() from stdlib.h or execv(). On the other hand it seems more handy for work with UTF-8 in ruby extensions. Let me know, if I should remove this commit.

Please also note, that there's PR #2877 which is also related to UTF-8 on Windows and was postponed to ruby-3.0.

Implements issue ruby#12650: 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.
@nobu

nobu commented Nov 27, 2020

Copy link
Copy Markdown
Member

Why just env encoding leaving the locale encoding?

d9997d3 seems to change nothing.

@larskanis

Copy link
Copy Markdown
Contributor Author

Why just env encoding leaving the locale encoding?

Not sure if I understand you right. If your question is about "What's wrong with keeping the current behavior of using locale encoding?", there are some reasons:

  1. ENV reading is limited to locale encoding, although Windows isn't. Asian codepages are comparatively rich of characters, but 8 bit codepages in Europe aren't. For instance a username that is unrepresentable in locale encoding happens at times.
ENV["USERNAME"] = "Питер"  # => "Питер"
ENV["USERNAME"]            # => "?????"   (not codable in CP850)
  1. Since source code is encoded in UTF-8 typical encoding incompatibilities arise, even if the value in the environment variable is valid in the current locale:
ENV['USERNAME'] = "Sören"
ENV['USERNAME']           # => "S\x94ren"  (converted to CP850)
ENV['USERNAME'] =~ /Sör/  # => Encoding::CompatibilityError (incompatible encoding regexp match (UTF-8 regexp with CP850 string))

@larskanis

Copy link
Copy Markdown
Contributor Author

d9997d3 seems to change nothing.

It changes nothing unless non-ASCII characters are used in RUBYSHELL or COMSPEC variables, which is rare.

@nobu

nobu commented Nov 28, 2020

Copy link
Copy Markdown
Member

By #define getenv(name) w32_getenv(name, cp), getenv("RUBYSHELL") is expanded as w32_getenv("RUBYSHELL", cp) for instance.
Isn't it same as your patch?

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.
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.
@larskanis

Copy link
Copy Markdown
Contributor Author

@nobu You're absolutely right! After second reading it is just a cosmetic change. Still I find it a valuable change, since the implicit usage of cp by the macro is misleading. So I changed the wording in the commit and in the description above.

@nobu

nobu commented Nov 28, 2020

Copy link
Copy Markdown
Member

Found that this getenv is necessary for dln_find.c too.

@nobu

nobu commented Nov 28, 2020

Copy link
Copy Markdown
Member

Revived the macro by 3db21cf.

@larskanis

Copy link
Copy Markdown
Contributor Author

That usage in dln_find.c is tricky - I wonder why CI didn't fail. But anyway, let me know if I should rebase the PR to remove the second commit and to integrate the latest patches that fix the MJIT failures in CI!

@nobu

nobu commented Nov 28, 2020

Copy link
Copy Markdown
Member

The failures seem caused by MJIT, unrelated to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants