aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-19 03:10:12 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-19 03:10:12 +0000
commit9e36a8421df139cb264a4f621180122879398c9d (patch)
tree77998ac89b0fad3626652a2bd77dd0ca2be06cf4
parent55f87e75866b6e5c1daf7c7624ccb633784243f0 (diff)
downloadruby-9e36a8421df139cb264a4f621180122879398c9d.tar.gz
re.c: fix match?
* re.c (rb_reg_match_m_p): fix match against empty string. rb_str_offset returns the end when the position exceeds the length. fix the range parameter of onig_search. [ruby-core:75604] [Bug #12394] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55069 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--re.c23
-rw-r--r--test/ruby/test_regexp.rb7
3 files changed, 24 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index feda75078d..f70d2191db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu May 19 12:10:10 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * re.c (rb_reg_match_m_p): fix match against empty string.
+ rb_str_offset returns the end when the position exceeds the
+ length. fix the range parameter of onig_search.
+ [ruby-core:75604] [Bug #12394]
+
Thu May 19 11:37:36 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* re.c (rb_reg_match_m_p): should return false if no match, as the
diff --git a/re.c b/re.c
index c83b3f5ba2..01d28aa177 100644
--- a/re.c
+++ b/re.c
@@ -3227,6 +3227,7 @@ rb_reg_match_m_p(int argc, VALUE *argv, VALUE re)
regex_t *reg;
onig_errmsg_buffer err = "";
OnigPosition result;
+ const UChar *start, *end;
int tmpreg;
rb_scan_args(argc, argv, "11", &str, &initpos);
@@ -3234,27 +3235,23 @@ rb_reg_match_m_p(int argc, VALUE *argv, VALUE re)
str = SYMBOL_P(str) ? rb_sym2str(str) : rb_str_to_str(str);
if (argc == 2) {
pos = NUM2LONG(initpos);
- if (pos == 0) goto run;
if (pos < 0) {
pos += NUM2LONG(rb_str_length(str));
- if (pos == 0) goto run;
if (pos < 0) return Qfalse;
-
}
- pos = rb_str_offset(str, pos);
- }
-run:
- if (pos >= RSTRING_LEN(str)) {
- return Qfalse;
+ if (pos > 0) {
+ long len = 0;
+ char *beg = rb_str_subpos(str, pos, &len);
+ if (!beg) return Qfalse;
+ pos = beg - RSTRING_PTR(str);
+ }
}
reg = rb_reg_prepare_re0(re, str, err);
tmpreg = reg != RREGEXP_PTR(re);
if (!tmpreg) RREGEXP(re)->usecnt++;
- result = onig_search(reg,
- ((UChar*)RSTRING_PTR(str)),
- ((UChar*)RSTRING_END(str)),
- ((UChar*)(RSTRING_PTR(str)) + pos),
- ((UChar*)RSTRING_PTR(str)),
+ start = ((UChar*)RSTRING_PTR(str));
+ end = start + RSTRING_LEN(str);
+ result = onig_search(reg, start, end, start + pos, end,
NULL, ONIG_OPTION_NONE);
if (!tmpreg) RREGEXP(re)->usecnt--;
if (tmpreg) {
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 8f5c9ceaa2..c25433b1ff 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -528,14 +528,21 @@ class TestRegexp < Test::Unit::TestCase
def test_match_p
/backref/ =~ 'backref'
+ # must match here, but not in a separate method, e.g., assert_send,
+ # to check if $~ is affected or not.
assert_equal(false, //.match?(nil))
+ assert_equal(true, //.match?(""))
assert_equal(true, /.../.match?(:abc))
assert_raise(TypeError) { /.../.match?(Object.new) }
+ assert_equal(true, /b/.match?('abc'))
+ assert_equal(true, /b/.match?('abc', 1))
assert_equal(true, /../.match?('abc', 1))
assert_equal(true, /../.match?('abc', -2))
assert_equal(false, /../.match?("abc", -4))
assert_equal(false, /../.match?("abc", 4))
assert_equal(true, /../n.match?("\u3042" + '\x', 1))
+ assert_equal(true, /\z/.match?(""))
+ assert_equal(true, /\z/.match?("abc"))
assert_equal('backref', $&)
end