regexp match /.../n against to UTF-8 string

rails3.1.3からrails3.1.8に変更してからの苦労しているところ。

警告が出ている 

c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.1.8/lib/active_support/core_ext/string/output_safety.rb:23: warning: regexp match /.../n against to UTF-8 string

 
調べてみるとRack::Utils#escapeがRuby1.9.1だと何かアレな件(As Sloth As Possible)を見つける。

  1. escape中でunpackするときに、String#sizeを使っている。1.8まではこのメソッドはバイト数を返してたけど、1.9では文字数を返すように仕様が変更されている。マルチバイトな文字列だと当然バイト数と文字数は一致しないので、途中で切れちゃうことになる。
  2. packして返ってくるのは単なるバイト列、つまりASCII-8BITのString。
  3. 1.8までは文字列がどんなエンコーディングであれ、unpackしてpackすればまた文字列に戻る。でも1.9ではunpackからpackの過程で元のエンコーディング情報は失なわれているので、明示的にエンコーディング情報を付加してやる必要がある。


対応策

c:/Ruby193/lib/ruby/gems/1.9.1/gems/activesupport-3.1.8/lib/active_support/core_ext/string/output_safety.rb

#        s.gsub(/[&"'><]/n) { |special| HTML_ESCAPE[special] }.html_safe
        s.gsub(/[&"'><]/) { |special| HTML_ESCAPE[special] }.html_safe