[前][次][番号順一覧][スレッド一覧]

ruby-changes:62566

From: Kasumi <ko1@a...>
Date: Thu, 13 Aug 2020 20:54:26 +0900 (JST)
Subject: [ruby-changes:62566] 014a4fda54 (master): rb_str_{index, rindex}_m: Handle /\K/ in pattern

https://git.ruby-lang.org/ruby.git/commit/?id=014a4fda54

From 014a4fda54cb6897ed54ea9c44376db3459fc46e Mon Sep 17 00:00:00 2001
From: Kasumi Hanazuki <kasumi@r...>
Date: Thu, 13 Aug 2020 02:26:09 +0000
Subject: 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]

diff --git a/string.c b/string.c
index e1c6e54..e984330 100644
--- a/string.c
+++ b/string.c
@@ -3676,8 +3676,14 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L3676
 	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) https://github.com/ruby/ruby/blob/trunk/string.c#L3833
 	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);
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 308ba80..489eee3 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1353,6 +1353,8 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L1353
 
     assert_nil("foo".index(//, -100))
     assert_nil($~)
+
+    assert_equal(2, S("abcdbce").index(/b\Kc/))
   end
 
   def test_insert
@@ -1525,6 +1527,8 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L1527
 
     assert_equal(3, "foo".rindex(//))
     assert_equal([3, 3], $~.offset(0))
+
+    assert_equal(5, S("abcdbce").rindex(/b\Kc/))
   end
 
   def test_rjust
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]