summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Gruber <[email protected]>2023-12-30 13:26:59 -0500
committerJeremy Evans <[email protected]>2024-01-01 13:28:26 -0800
commite12d4c654e3cb7a4473014610bc3bae41aaf811e (patch)
tree3184f19e8898ca9af24dd5d6ee22afad83fa0530
parent676748abcad62c021fc122d137f177d3c0f0f7a8 (diff)
Don't create T_MATCH object if /regexp/.match(string) doesn't match
Fixes [Bug #20104]
-rw-r--r--re.c9
-rw-r--r--test/ruby/test_regexp.rb12
-rw-r--r--tool/lib/envutil.rb8
3 files changed, 26 insertions, 3 deletions
diff --git a/re.c b/re.c
index cb8cc865b2..bf4dc5ccbf 100644
--- a/re.c
+++ b/re.c
@@ -1747,15 +1747,18 @@ rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_back
.range = reverse ? 0 : len,
};
- VALUE match = match_alloc(rb_cMatch);
- struct re_registers *regs = RMATCH_REGS(match);
+ struct re_registers regs = {0};
- OnigPosition result = rb_reg_onig_match(re, str, reg_onig_search, &args, regs);
+ OnigPosition result = rb_reg_onig_match(re, str, reg_onig_search, &args, &regs);
if (result == ONIG_MISMATCH) {
rb_backref_set(Qnil);
return ONIG_MISMATCH;
}
+ VALUE match = match_alloc(rb_cMatch);
+ rb_matchext_t *rm = RMATCH_EXT(match);
+ rm->regs = regs;
+
if (set_backref_str) {
RB_OBJ_WRITE(match, &RMATCH(match)->str, rb_str_new4(str));
}
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index be563dfa52..6973e21c7a 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -711,6 +711,18 @@ class TestRegexp < Test::Unit::TestCase
}
end
+ def test_match_no_match_no_matchdata
+ EnvUtil.without_gc do
+ h = {}
+ ObjectSpace.count_objects(h)
+ prev_matches = h[:T_MATCH] || 0
+ md = /[A-Z]/.match('1') # no match
+ ObjectSpace.count_objects(h)
+ new_matches = h[:T_MATCH] || 0
+ assert_equal prev_matches, new_matches, "Bug [#20104]"
+ end
+ end
+
def test_initialize
assert_raise(ArgumentError) { Regexp.new }
assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)})
diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb
index 9be0aac479..309a6af40f 100644
--- a/tool/lib/envutil.rb
+++ b/tool/lib/envutil.rb
@@ -254,6 +254,14 @@ module EnvUtil
end
module_function :under_gc_compact_stress
+ def without_gc
+ prev_disabled = GC.disable
+ yield
+ ensure
+ GC.enable unless prev_disabled
+ end
+ module_function :without_gc
+
def with_default_external(enc)
suppress_warning { Encoding.default_external = enc }
yield