rb_str_{index,rindex}_m: Handle /\K/ in pattern

When the pattern Regexp given to String#index and String#rindex
contain a /\K/ (lookbehind) operator, these methods return the
position where the beginning of the lookbehind pattern matches, while
they are expected to return the position where the \K matches.

```
# without patch
"abcdbce".index(/b\Kc/)  # => 1
"abcdbce".rindex(/b\Kc/)  # => 4
```

This patch fixes this problem by using BEG(0) instead of the return
value of rb_reg_search.

```
# with patch
"abcdbce".index(/b\Kc/)  # => 2
"abcdbce".rindex(/b\Kc/)  # => 5
```

Fixes [Bug #17118]
This commit is contained in:
Kasumi Hanazuki 2020-08-13 02:26:09 +00:00 коммит произвёл Nobuyoshi Nakada
Родитель 5d71eed1a7
Коммит 014a4fda54
2 изменённых файлов: 18 добавлений и 5 удалений

Просмотреть файл

@ -3676,8 +3676,14 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
rb_enc_check(str, sub), single_byte_optimizable(str));
pos = rb_reg_search(sub, str, pos, 0);
pos = rb_str_sublen(str, pos);
if (rb_reg_search(sub, str, pos, 0) < 0) {
return Qnil;
} else {
VALUE match = rb_backref_get();
struct re_registers *regs = RMATCH_REGS(match);
pos = rb_str_sublen(str, BEG(0));
return LONG2NUM(pos);
}
}
else {
StringValue(sub);
@ -3827,9 +3833,12 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
enc, single_byte_optimizable(str));
pos = rb_reg_search(sub, str, pos, 1);
pos = rb_str_sublen(str, pos);
if (pos >= 0) return LONG2NUM(pos);
if (rb_reg_search(sub, str, pos, 1) >= 0) {
VALUE match = rb_backref_get();
struct re_registers *regs = RMATCH_REGS(match);
pos = rb_str_sublen(str, BEG(0));
return LONG2NUM(pos);
}
}
else {
StringValue(sub);

Просмотреть файл

@ -1353,6 +1353,8 @@ CODE
assert_nil("foo".index(//, -100))
assert_nil($~)
assert_equal(2, S("abcdbce").index(/b\Kc/))
end
def test_insert
@ -1525,6 +1527,8 @@ CODE
assert_equal(3, "foo".rindex(//))
assert_equal([3, 3], $~.offset(0))
assert_equal(5, S("abcdbce").rindex(/b\Kc/))
end
def test_rjust