From 0e653eb4c2f1e9ed74db2c2433cf2f5a37b54bca Mon Sep 17 00:00:00 2001 From: dearblue Date: Tue, 4 Nov 2025 21:24:01 +0900 Subject: [PATCH] Fixed use-after-free with `Set#join` The `mrb_obj_as_string()` function can call the `#to_s` method. String addresses and string lengths obtained outside the `KSET_FOREACH()` loop may become invalid. --- mrbgems/mruby-set/src/set.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/mrbgems/mruby-set/src/set.c b/mrbgems/mruby-set/src/set.c index eaa1f1d8b..1ee7e3491 100644 --- a/mrbgems/mruby-set/src/set.c +++ b/mrbgems/mruby-set/src/set.c @@ -1023,14 +1023,6 @@ set_join(mrb_state *mrb, mrb_value self) return mrb_str_new_lit(mrb, ""); } - /* Get separator string */ - const char *sep_ptr = ""; - mrb_int sep_len = 0; - if (!mrb_nil_p(separator)) { - sep_ptr = RSTRING_PTR(separator); - sep_len = RSTRING_LEN(separator); - } - /* Create result string */ mrb_value result = mrb_str_new_capa(mrb, 64); /* Initial capacity */ mrb_bool first = TRUE; @@ -1039,7 +1031,9 @@ set_join(mrb_state *mrb, mrb_value self) int ai = mrb_gc_arena_save(mrb); KSET_FOREACH(set, k) { if (!first) { - mrb_str_cat(mrb, result, sep_ptr, sep_len); + if (!mrb_nil_p(separator)) { + mrb_str_cat(mrb, result, RSTRING_PTR(separator), RSTRING_LEN(separator)); + } } else { first = FALSE;