From fa85d23ff4a02985ebfe0716b0ff768f5b4fe13d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 27 May 2025 22:24:28 +0900 Subject: [PATCH] [Bug #21380] Prohibit modification in String#split block Reported at https://hackerone.com/reports/3163876 --- string.c | 11 +++++++---- test/ruby/test_string.rb | 7 +++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/string.c b/string.c index faa4a16106..3ddd64ef25 100644 --- a/string.c +++ b/string.c @@ -9748,11 +9748,15 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) } } -#define SPLIT_STR(beg, len) (empty_count = split_string(result, str, beg, len, empty_count)) +#define SPLIT_STR(beg, len) ( \ + empty_count = split_string(result, str, beg, len, empty_count), \ + str_mod_check(str, str_start, str_len)) beg = 0; char *ptr = RSTRING_PTR(str); - char *eptr = RSTRING_END(str); + char *const str_start = ptr; + const long str_len = RSTRING_LEN(str); + char *const eptr = str_start + str_len; if (split_type == SPLIT_TYPE_AWK) { char *bptr = ptr; int skip = 1; @@ -9813,7 +9817,6 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) } } else if (split_type == SPLIT_TYPE_STRING) { - char *str_start = ptr; char *substr_start = ptr; char *sptr = RSTRING_PTR(spat); long slen = RSTRING_LEN(spat); @@ -9830,6 +9833,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) continue; } SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start); + str_mod_check(spat, sptr, slen); ptr += end + slen; substr_start = ptr; if (!NIL_P(limit) && lim <= ++i) break; @@ -9837,7 +9841,6 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str) beg = ptr - str_start; } else if (split_type == SPLIT_TYPE_CHARS) { - char *str_start = ptr; int n; if (result) result = rb_ary_new_capa(RSTRING_LEN(str)); diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 1011967fe9..138756eac5 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -1869,6 +1869,13 @@ CODE result = []; S("aaa,bbb,ccc,ddd").split(/,/) {|s| result << s.gsub(/./, "A")} assert_equal(["AAA"]*4, result) + + s = S("abc ") * 20 + assert_raise(RuntimeError) { + 10.times do + s.split {s.prepend("xxx" * 100)} + end + } ensure EnvUtil.suppress_warning {$; = fs} end