summaryrefslogtreecommitdiff
path: root/re.c
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2023-12-24 09:08:01 -0500
committerPeter Zhu <[email protected]>2023-12-24 11:04:41 -0500
commitf0efeddd41f96d3afae9af73a3dc594d86614f4b (patch)
tree0bbdeed0270ccd7789ebef569b50445c1608e0ea /re.c
parent8ad8803bb4aed01dfe56e42dc7c131b6bf307655 (diff)
Fix Regexp#inspect for GC compaction
rb_reg_desc was not safe for GC compaction because it took in the C string and length but not the backing String object so it get moved during compaction. This commit changes rb_reg_desc to use the string from the Regexp object. The test fails when RGENGC_CHECK_MODE is turned on: TestRegexp#test_inspect_under_gc_compact_stress [test/ruby/test_regexp.rb:474]: <"(?-mix:\\/)|"> expected but was <"/\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00/">.
Diffstat (limited to 're.c')
-rw-r--r--re.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/re.c b/re.c
index ef49281454..cb8cc865b2 100644
--- a/re.c
+++ b/re.c
@@ -450,7 +450,7 @@ rb_reg_expr_str(VALUE str, const char *s, long len,
}
static VALUE
-rb_reg_desc(const char *s, long len, VALUE re)
+rb_reg_desc(VALUE re)
{
rb_encoding *enc = rb_enc_get(re);
VALUE str = rb_str_buf_new2("/");
@@ -463,7 +463,11 @@ rb_reg_desc(const char *s, long len, VALUE re)
else {
rb_enc_associate(str, rb_usascii_encoding());
}
- rb_reg_expr_str(str, s, len, enc, resenc, '/');
+
+ VALUE src_str = RREGEXP_SRC(re);
+ rb_reg_expr_str(str, RSTRING_PTR(src_str), RSTRING_LEN(src_str), enc, resenc, '/');
+ RB_GC_GUARD(src_str);
+
rb_str_buf_cat2(str, "/");
if (re) {
char opts[OPTBUF_SIZE];
@@ -522,7 +526,7 @@ rb_reg_inspect(VALUE re)
if (!RREGEXP_PTR(re) || !RREGEXP_SRC(re) || !RREGEXP_SRC_PTR(re)) {
return rb_any_to_s(re);
}
- return rb_reg_desc(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), re);
+ return rb_reg_desc(re);
}
static VALUE rb_reg_str_with_term(VALUE re, int term);
@@ -670,12 +674,12 @@ rb_reg_str_with_term(VALUE re, int term)
return str;
}
-NORETURN(static void rb_reg_raise(const char *s, long len, const char *err, VALUE re));
+NORETURN(static void rb_reg_raise(const char *err, VALUE re));
static void
-rb_reg_raise(const char *s, long len, const char *err, VALUE re)
+rb_reg_raise(const char *err, VALUE re)
{
- VALUE desc = rb_reg_desc(s, len, re);
+ VALUE desc = rb_reg_desc(re);
rb_raise(rb_eRegexpError, "%s: %"PRIsVALUE, err, desc);
}
@@ -1634,7 +1638,7 @@ rb_reg_prepare_re(VALUE re, VALUE str)
if (r) {
onig_error_code_to_str((UChar*)err, r, &einfo);
- rb_reg_raise(pattern, RREGEXP_SRC_LEN(re), err, re);
+ rb_reg_raise(err, re);
}
reg->timelimit = timelimit;
@@ -1667,7 +1671,7 @@ rb_reg_onig_match(VALUE re, VALUE str,
if (result != ONIG_MISMATCH) {
onig_errmsg_buffer err = "";
onig_error_code_to_str((UChar*)err, (int)result);
- rb_reg_raise(RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), err, re);
+ rb_reg_raise(err, re);
}
}