Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 528f28d4b847
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a53970cf5ee5
Choose a head ref
  • 3 commits
  • 1 file changed
  • 2 contributors

Commits on Mar 30, 2016

  1. Workaround for JRuby bug with UTF-8 encoding on non-English Windows

    We discovered this with a customer yesterday. DNS resolving (using `Resolv::DNS#getaddresses`) failed. It turned out that the underlying problem was that the way `win32/registry.rb` retrieves error messages from Windows is flawed, under certain circumstances.
    
    The bug only appears if:
    
    - `JAVA_OPTS` includes `-Dfile.encoding=UTF-8`
    - The environment you run it on is a _non-English_ Windows installation, or more specifically: a Windows installation where the error message(s) include some non-ASCII character. The specific use case here is a Swedish Windows installation, where the error message for error number 2 (File not found) reads as "Filen du söker finns inte", or something similar. (The debugging here was complicated by the fact that I don't have a Swedish Windows myself, only the customer).
    
    Here is a test script that reproduces the problem given that you have a Swedish Windows:
    
    ```ruby
    
    require 'win32/resolv'
    puts Encoding.locale_charmap
    puts Win32::Resolv.send(:get_info).inspect
    ```
    
    Since I don't have a Swedish Windows, I managed to reproduce the same error locally by adding this code into the `Error` constructor:
    
    ```ruby
    msg = "Malm\xf6, G\xf6teborg och V\xe4xj\xf6"
    ```
    
    That gives me the same error: `ArgumentError: invalid byte sequence in UTF-8`. The original bug occurs in the `msg.tr` call, since the string it operates on is _marked_ as UTF-8 (because of the `force_encoding` call), where it is in fact Windows-1252 encoded (since we call `FormatMessageA`, which returns Windows-1252 encoded strings...). IMHO, this is clearly a bug.
    
    ---
    
    Now, to the solution. The "correct" approach would be to not use the ANSI version of the system call _at all_, but instead use the "wide" version. This is the approach MRI has taken, the bug was fixed there almost 3 years ago. :) ruby/ruby@9db6beb is the specific commit, fixing the bug reported in this issue: https://bugs.ruby-lang.org/issues/8508
    
    I tried that first, by copying over their current version of the `Error` class. The only problem is that it depends on `win32/importer`, which we don't have, which in turn depends on `fiddle/import` which we don't seem to have either. You get the picture.
    
    Therefore, I tried with a simpler workaround instead: _if_ we get an exception in this method, let's just retry by fetching the `en-US` error message instead. (inspired by how the code on the MRI side now looks: https://github.com/ruby/ruby/blob/trunk/ext/win32/lib/win32/registry.rb)
    I have tested this with the customer; it works correctly as far as the code no longer crashes. _But_, it fails to retrieve the English error message (possibly because it's not available on that Windows installation). I am willing to live with that for now; if someone wants to fix that part as well, be my guest. The critical part for me and the customer is that the code must not crash on non-ASCII Windows installations.
    perlun committed Mar 30, 2016

    Verified

    This commit was signed with the committer’s verified signature.
    makenowjust Hiroya Fujinami
    Copy the full SHA
    48f5908 View commit details

Commits on Mar 31, 2016

  1. Copy the full SHA
    afc3763 View commit details
  2. Merge pull request #3767 from ecraft/fix-win32-registry-error-handlin…

    …g-bug-with-utf8-windows-other-languages
    
    Workaround for JRuby bug with UTF-8 encoding on non-English Windows
    enebo committed Mar 31, 2016
    Copy the full SHA
    a53970c View commit details
Showing with 8 additions and 4 deletions.
  1. +8 −4 lib/ruby/1.9/win32/registry.rb
12 changes: 8 additions & 4 deletions lib/ruby/1.9/win32/registry.rb
Original file line number Diff line number Diff line change
@@ -63,6 +63,10 @@ module Win32
=end rdoc

WCHAR = Encoding::UTF_16LE
WCHAR_SPACE = "\0".encode(WCHAR).freeze
LOCALE = Encoding.find(Encoding.locale_charmap)

class Registry

#
@@ -160,12 +164,12 @@ module Constants
# Error
#
class Error < ::StandardError
FormatMessageA = Win32API.new('kernel32.dll', 'FormatMessageA', 'LPLLPLP', 'L')
FormatMessageW = Win32API.new('kernel32.dll', 'FormatMessageW', 'LPLLPLP', 'L')
def initialize(code)
@code = code
msg = "\0".force_encoding(Encoding::ASCII_8BIT) * 1024
len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0)
msg = msg[0, len].force_encoding(Encoding.find(Encoding.locale_charmap))
msg = WCHAR_SPACE * 1024
len = FormatMessageW.call(0x1200, 0, code, 0, msg, 1024, 0)
msg = msg[0, len].encode(Encoding.locale_charmap)
super msg.tr("\r", '').chomp
end
attr_reader :code