Project

General

Profile

Actions

Bug #14384

closed

CompatibilityError is thrown when formatting a non-ASCII string with a binary string argument

Added by joshc (Josh C) over 4 years ago. Updated over 4 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
[ruby-core:84972]

Description

The following script:

# coding: utf-8
require 'socket'
begin
  TCPSocket.open('nowhere', 80)
rescue => e
  puts "証明書をリクエストできませんでした: %s" % e.message
end

Produces an error on Windows instead of printing message:

PS C:\work\puppet> ruby tcp.rb
tcp.rb:7:in `%': incompatible character encodings: UTF-8 and ASCII-8BIT (Encoding::CompatibilityError)
        from tcp.rb:7:in `rescue in <main>'
        from tcp.rb:4:in `<main>'

The SocketError's exception message is a binary string (ASCII_8BIT). The exception message comes from the rb_w32_strerror method which uses FormatMessage instead of FormatMessageW.

The following works around the issue:

puts "証明書をリクエストできませんでした: %s".encode(Encoding.default_external) % e.message.force_encoding(Encoding.default_external)

The exception is not raised if the format string consists of ASCII only, e.g. puts "Connection failed: %s" % e.message, however, the output is not formatted correctly:

PS C:\work\puppet> ruby tcp.rb
Connection failed: getaddrinfo: ���̂悤�ȃz�X�g�͕s���ł��B

Changing that to:

puts "Connection failed: %s" % e.message.force_encoding(Encoding.default_external)

Does correctly output the message:

PS C:\work\puppet> ruby tcp.rb
Connection failed: getaddrinfo: そのようなホストは不明です。

So the issue is a combination of the encoding of the format and argument strings.

My environment:

PS C:\work\puppet> gem env
RubyGems Environment:
  - RUBYGEMS VERSION: 2.5.2
  - RUBY VERSION: 2.3.3 (2016-11-21 patchlevel 222) [x64-mingw32]
  - INSTALLATION DIRECTORY: C:/Ruby23-x64/lib/ruby/gems/2.3.0
  - USER INSTALLATION DIRECTORY: C:/Users/Administrator/.gem/ruby/2.3.0
  - RUBY EXECUTABLE: C:/Ruby23-x64/bin/ruby.exe
  - EXECUTABLE DIRECTORY: C:/Ruby23-x64/bin
  - SPEC CACHE DIRECTORY: C:/Users/Administrator/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: C:/ProgramData
  - RUBYGEMS PLATFORMS:
    - ruby
    - x64-mingw32
  - GEM PATHS:
     - C:/Ruby23-x64/lib/ruby/gems/2.3.0
     - C:/Users/Administrator/.gem/ruby/2.3.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - C:\Ruby23-x64\bin
     - C:\Windows\system32
     - C:\Windows
     - C:\Windows\System32\Wbem
     - C:\Windows\System32\WindowsPowerShell\v1.0\
     - C:\Program Files\Git\cmd
     - C:\Packer\SysInternals
PS C:\work\puppet>
PS C:\work\puppet> ruby --version
ruby 2.3.3p222 (2016-11-21 revision 56859) [x64-mingw32]
PS C:\work\puppet> gem --version
2.5.2
Actions #1

Updated by nobu (Nobuyoshi Nakada) over 4 years ago

  • Status changed from Open to Closed

Applied in changeset trunk|r62017.


init.c: encode socket error message

  • ext/socket/init.c (rsock_raise_socket_error): on Windows, encode
    error messages from wide characters to the default encodings.
    [ruby-core:84972] [Bug #14384]

Updated by nobu (Nobuyoshi Nakada) over 4 years ago

The message does not come from rb_w32_strerror but gai_strerror in WinSock2 library.

Actions

Also available in: Atom PDF