From 12285fc1094bcbe290a8a12555f175c1eb41c88d Mon Sep 17 00:00:00 2001 From: nagachika Date: Mon, 16 Jun 2014 15:42:56 +0000 Subject: [PATCH] merge revision(s) r45521,r45523,r45551: [Backport #9699] win32.c: wchar conversion * win32/win32.c (rb_w32_wstr_to_mbstr, rb_w32_mbstr_to_wstr): make WCHAR/mb conversion functions public. * dln.c (dln_load): use wchar version to load a library in non-ascii path on Windows. based on the patch by Bugra Barin in [ruby-core:61845]. [Bug #9699] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@46450 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ dln.c | 15 ++++++++++----- ext/-test-/win32/dln/empty/empty.c | 4 ++++ ext/-test-/win32/dln/empty/extconf.rb | 3 +++ include/ruby/win32.h | 2 ++ test/-ext-/win32/test_dln.rb | 22 ++++++++++++++++++++++ version.h | 2 +- win32/win32.c | 12 ++++++------ 8 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 ext/-test-/win32/dln/empty/empty.c create mode 100644 ext/-test-/win32/dln/empty/extconf.rb diff --git a/ChangeLog b/ChangeLog index af631ee786..250a5d0087 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue Jun 17 00:37:15 2014 Bugra Barin + + * dln.c (dln_load): use wchar version to load a library in + non-ascii path on Windows. based on the patch by Bugra Barin + in [ruby-core:61845]. [Bug #9699] + Tue Jun 17 00:26:59 2014 Nobuyoshi Nakada * process.c (obj2uid, obj2gid): now getpwnam_r() and getgrnam_r() diff --git a/dln.c b/dln.c index e6b20d54e3..85ebe27cae 100644 --- a/dln.c +++ b/dln.c @@ -1255,20 +1255,25 @@ dln_load(const char *file) #if defined _WIN32 && !defined __CYGWIN__ HINSTANCE handle; - char winfile[MAXPATHLEN]; + WCHAR *winfile; char message[1024]; void (*init_fct)(); char *buf; - if (strlen(file) >= MAXPATHLEN) dln_loaderror("filename too long"); - /* Load the file as an object one */ init_funcname(&buf, file); - strlcpy(winfile, file, sizeof(winfile)); + /* Convert the file path to wide char */ + winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL); + if (!winfile) { + dln_memerror(); + } /* Load file */ - if ((handle = LoadLibrary(winfile)) == NULL) { + handle = LoadLibraryW(winfile); + free(winfile); + + if (!handle) { error = dln_strerror(); goto failed; } diff --git a/ext/-test-/win32/dln/empty/empty.c b/ext/-test-/win32/dln/empty/empty.c new file mode 100644 index 0000000000..c4f94f1644 --- /dev/null +++ b/ext/-test-/win32/dln/empty/empty.c @@ -0,0 +1,4 @@ +void +Init_empty(void) +{ +} diff --git a/ext/-test-/win32/dln/empty/extconf.rb b/ext/-test-/win32/dln/empty/extconf.rb new file mode 100644 index 0000000000..a4efed90c9 --- /dev/null +++ b/ext/-test-/win32/dln/empty/extconf.rb @@ -0,0 +1,3 @@ +if $mingw or $mswin + create_makefile("-test-/win32/dln/empty") +end diff --git a/include/ruby/win32.h b/include/ruby/win32.h index 070bab28f9..067ac010da 100644 --- a/include/ruby/win32.h +++ b/include/ruby/win32.h @@ -772,6 +772,8 @@ int rb_w32_wait_events_blocking(HANDLE *events, int num, DWORD timeout); int rb_w32_time_subtract(struct timeval *rest, const struct timeval *wait); int rb_w32_wrap_io_handle(HANDLE, int); int rb_w32_unwrap_io_handle(int); +WCHAR *rb_w32_mbstr_to_wstr(UINT, const char *, int, long *); +char *rb_w32_wstr_to_mbstr(UINT, const WCHAR *, int, long *); /* == ***CAUTION*** diff --git a/test/-ext-/win32/test_dln.rb b/test/-ext-/win32/test_dln.rb index 7c5fe61f59..c9065e66fb 100644 --- a/test/-ext-/win32/test_dln.rb +++ b/test/-ext-/win32/test_dln.rb @@ -1,4 +1,6 @@ require 'test/unit' +require 'tmpdir' +require 'rbconfig' require_relative '../../ruby/envutil' module Bug @@ -8,6 +10,26 @@ module Bug bug = '[Bug #6303]' assert_in_out_err(['-r-test-/win32/dln', '-eexit'], '', [], [], bug, timeout: 10) end + + def test_nonascii_load + bug9699 = '[ruby-core:61845] [Bug #9699]' + so = "-test-/win32/dln/empty." + RbConfig::CONFIG["DLEXT"] + so = $:.find {|d| d = ::File.join(d, so); break d if ::File.exist?(d)} + assert_not_nil(so) + Dir.mkdir(dir = ::File.join(testdir = Dir.mktmpdir("test"), "\u{30c6 30b9 30c8}")) + ::File.copy_stream(so, ::File.join(dir, ::File.basename(so))) + assert_separately(['-', bug9699, testdir, ::File.basename(so)], <<-'end;') + bug, dir, so = *ARGV + assert_nothing_raised(LoadError, bug) do + require ::File.join(dir, "\u{30c6 30b9 30c8}", so) + end + end; + ensure + ::File.unlink(::File.join(dir, ::File.basename(so))) rescue nil + Dir.rmdir(dir) rescue nil + Dir.rmdir(testdir) rescue nil + end + end end end if /mswin|mingw/ =~ RUBY_PLATFORM diff --git a/version.h b/version.h index edb9e01c3a..276892b411 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ #define RUBY_VERSION "2.1.2" #define RUBY_RELEASE_DATE "2014-06-17" -#define RUBY_PATCHLEVEL 130 +#define RUBY_PATCHLEVEL 131 #define RUBY_RELEASE_YEAR 2014 #define RUBY_RELEASE_MONTH 6 diff --git a/win32/win32.c b/win32/win32.c index 9fd981ec56..a2ced890ff 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -1197,8 +1197,8 @@ is_batch(const char *cmd) } static UINT filecp(void); -static WCHAR *mbstr_to_wstr(UINT, const char *, int, long *); -static char *wstr_to_mbstr(UINT, const WCHAR *, int, long *); +#define mbstr_to_wstr rb_w32_mbstr_to_wstr +#define wstr_to_mbstr rb_w32_wstr_to_mbstr #define acp_to_wstr(str, plen) mbstr_to_wstr(CP_ACP, str, -1, plen) #define wstr_to_acp(str, plen) wstr_to_mbstr(CP_ACP, str, -1, plen) #define filecp_to_wstr(str, plen) mbstr_to_wstr(filecp(), str, -1, plen) @@ -1952,8 +1952,8 @@ filecp(void) } /* License: Ruby's */ -static char * -wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen, long *plen) +char * +rb_w32_wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen, long *plen) { char *ptr; int len = WideCharToMultiByte(cp, 0, wstr, clen, NULL, 0, NULL, NULL); @@ -1968,8 +1968,8 @@ wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen, long *plen) } /* License: Ruby's */ -static WCHAR * -mbstr_to_wstr(UINT cp, const char *str, int clen, long *plen) +WCHAR * +rb_w32_mbstr_to_wstr(UINT cp, const char *str, int clen, long *plen) { WCHAR *ptr; int len = MultiByteToWideChar(cp, 0, str, clen, NULL, 0);