Project

General

Profile

Actions

Bug #3296

closed

windows で iconv.dll の使用する MSVC runtime DLL のバージョンが、ruby 本体が使用するものと一致していない場合に[BUG]が出る。

Added by tarui (Masaya Tarui) about 12 years ago. Updated about 11 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
ruby -v:
ruby 1.9.2dev (2010-05-14 revision 27797) [i386-mswin32_90]
Backport:

Description

=begin
樽家です。

ランタイムが一致していないiconv.dllをロードする環境で、以下のソース

require 'iconv'

Iconv.iconv("utf-8", "SJIS", "heh")
Iconv.iconv("utf-8", "X-UKNOWN", "heh")

を実行すると、
/soft/iconv.rb:4: [BUG] rb_sys_fail(iconv("utf-8", "X-UKNOWN")) - errno == 0
と言われます。
ランタイムが一致していない場合、errnoをうまく更新できないために、
iconvで失敗した場合に、Iconv::BrokenLibrary例外 を出力するのが正しいはずです。

所で、根本的にはerrnoがうまく取れればいいため、以下のようなPatchを書いてみました。
iconv.dllで使用している _errno() を調べてそれを参照するようにします。
取り込み可能でしょうか?

Index: include/ruby/win32.h

--- include/ruby/win32.h (リビジョン 27790)
+++ include/ruby/win32.h (作業コピー)
@@ -274,6 +274,9 @@
extern int fcntl(int, int, ...);
extern rb_pid_t rb_w32_getpid(void);
extern rb_pid_t rb_w32_getppid(void);
+
+extern void *rb_w32_GetImportFunctionPtr(const char *,const char *);
+
#if !defined(BORLANDC)
extern int rb_w32_isatty(int);
#endif
Index: win32/win32.c

--- win32/win32.c (リビジョン 27790)
+++ win32/win32.c (作業コピー)
@@ -29,6 +29,8 @@
#include <share.h>
#include <shlobj.h>
#include <mbstring.h>
+#include <imagehlp.h>
+
#if _MSC_VER >= 1400
#include <crtdbg.h>
#include <rtcapi.h>
@@ -5641,3 +5643,32 @@

  return *ip < 0;

}
#endif
+
+void *
+rb_w32_GetImportFunctionPtr(const char *modname,const char *funcname){

  • HMODULE hmod;
  • ULONG size;
  • const IMAGE_IMPORT_DESCRIPTOR* desc;
  • hmod = GetModuleHandle(modname);
  • if(!hmod)return NULL;
  • desc = ImageDirectoryEntryToData(hmod,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
  • if(!desc)return NULL;
  • while(desc->Name){
  • PIMAGE_THUNK_DATA piat,pint;
  • PIMAGE_IMPORT_BY_NAME pii;
  • pint = (PIMAGE_THUNK_DATA)((char *)hmod + desc->Characteristics);
  • piat = (PIMAGE_THUNK_DATA)((char *)hmod + desc->FirstThunk);
  • while(piat->u1.Function){
  •  pii =  (PIMAGE_IMPORT_BY_NAME)((char *)hmod+ pint->u1.AddressOfData);
    
  •  if(strcmp(pii->Name,funcname)==0){
    
  •  return (void *)piat->u1.Function;
    
  •  }
    
  •  piat++;
    
  •  pint++;
    
  • }
  • desc++;
  • }
  • return NULL;
    +}

Index: win32/Makefile.sub

--- win32/Makefile.sub (リビジョン 27790)
+++ win32/Makefile.sub (作業コピー)
@@ -212,7 +212,7 @@
EXTLIBS =
!endif
!if !defined(LIBS)
-LIBS = oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib $(EXTLIBS)
+LIBS = oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib imagehlp.lib $(EXTLIBS)
!endif
!if "$(ENABLE_WIN95)" == "yes"
LIBS = unicows.lib $(LIBS)
Index: ext/iconv/iconv.c

--- ext/iconv/iconv.c (リビジョン 27790)
+++ ext/iconv/iconv.c (作業コピー)
@@ -130,6 +130,14 @@

static VALUE charset_map;

+#ifdef _WIN32
+static int* (* _iconv_errno)(void);
+#undef errno
+#define errno (_iconv_errno())
+#endif
+
+
/

  • Document-method: charset_map

  • call-seq: Iconv.charset_map
    @@ -1212,5 +1220,12 @@

    rb_gc_register_address(&charset_map);
    charset_map = rb_hash_new();
    rb_define_singleton_method(rb_cIconv, "charset_map", charset_map_get, 0);

+#ifdef _WIN32

  • _iconv_errno = rb_w32_GetImportFunctionPtr("iconv.dll","_errno");
  • if(!_iconv_errno)
  • _iconv_errno = _errno;
    +#endif

}
=end

Actions #1

Updated by nobu (Nobuyoshi Nakada) about 12 years ago

=begin
なかだです。

At Sat, 15 May 2010 01:24:56 +0900,
masaya tarui wrote in [ruby-dev:41317]:

所で、根本的にはerrnoがうまく取れればいいため、以下のようなPatchを書いてみました。
iconv.dllで使用している _errno() を調べてそれを参照するようにします。
取り込み可能でしょうか?

これだけのためにそこまでする必要あるかなぁ、というのが正直な感想
ですが、それは置いておくにしてもこれだけでは効果がないと思います。
なぜなら、iconv.soから見えるerrnoを変えたところでrb_sys_fail()か
ら見えるerrnoにはまったく変わりが無いからです。

この問題はiconvに限らないので、できることなら拡張ライブラリをあ
まりいじらずに自動的に解決できる方法があるといいのですが、中には
複数の外部ライブラリをリンクするものもあったりするので、ちょっと
難しそうに思えます。

--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
中田 伸悦

=end

Actions #2

Updated by nobu (Nobuyoshi Nakada) about 12 years ago

  • Status changed from Open to Closed

=begin
This issue was solved with changeset r27805.
Masaya, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Actions

Also available in: Atom PDF