Project

General

Profile

Bug #1701

Regexp#match の pos 引数がマルチバイト文字に対応していない

Added by Murase (Masamitsu Murase) about 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
ruby -v:
ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-mswin32]

Description

=begin
Regexp#match の pos 引数がマルチバイト文字に対応していない

概要:
Regexp#match の第二引数 pos は、検索開始の位置を示していると思われますが、単位が「文字数」
ではなく、「バイト数」になっているようです。
この現象は Windows XP SP3 上、mswin32 版で発生することを確認しました。

例: "×あababab" という文字列から /ab/ を検索する場合。
(エンコーディングは UTF-8 です。)

m = /ab/.match("×あababab", 0)
=> m.begin(0)=2
m = /ab/.match("×あababab", 1)
=> m.begin(0)=2
m = /ab/.match("×あababab", 2)
=> m.begin(0)=2
m = /ab/.match("×あababab", 3)
=> m.begin(0)=2 (pos で与えた 3 よりも前にマッチしている)
m = /ab/.match("×あababab", 4)
=> m.begin(0)=2 (pos で与えた 4 よりも前にマッチしている)
m = /ab/.match("×あababab", 5)
=> m.begin(0)=2 (pos で与えた 5 よりも前にマッチしている)
m = /ab/.match("×あababab", 6)
=> m.begin(0)=4 (pos で与えた 6 よりも前にマッチしている)

詳細:
上記の例では、"×" と "あ" は UTF-8 でそれぞれ 2byte, 3byte なので、その分ずれが
生じていると思われます。

ソースコードをざっと見たところ、re.c 内の rb_reg_match_m 関数が reg_match_pos 関数を
呼んでおり、さらにその中で rb_reg_adjust_startpos 関数を呼んで pos が正しく文字境界に
来るように調整しています。
おそらく、ここでは rb_reg_adjust_startpos 関数による処理ではなく、string.c 内の
rb_str_index_m 関数で str_offset を用いて char 数を byte 数に変換しているように、
「char 数 => byte 数」の変換処理が必要ではないかと思います。
=end

History

#1

Updated by naruse (Yui NARUSE) about 10 years ago

  • Status changed from Open to Closed

=begin
r23916にて修正されました
=end

Also available in: Atom PDF