diff --git a/string.c b/string.c index 40b46eee57..a32b545642 100644 --- a/string.c +++ b/string.c @@ -2835,11 +2835,12 @@ rb_str_subpos(VALUE str, long beg, long *lenp) { long len = *lenp; long slen = -1L; - long blen = RSTRING_LEN(str); + const long blen = RSTRING_LEN(str); rb_encoding *enc = STR_ENC_GET(str); char *p, *s = RSTRING_PTR(str), *e = s + blen; if (len < 0) return 0; + if (beg < 0 && -beg < 0) return 0; if (!blen) { len = 0; } @@ -2857,7 +2858,8 @@ rb_str_subpos(VALUE str, long beg, long *lenp) } if (beg < 0) { if (len > -beg) len = -beg; - if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) { + if ((ENC_CODERANGE(str) == ENC_CODERANGE_VALID) && + (-beg * rb_enc_mbmaxlen(enc) < blen / 8)) { beg = -beg; while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0); p = e; @@ -2875,7 +2877,7 @@ rb_str_subpos(VALUE str, long beg, long *lenp) if (len == 0) goto end; } } - else if (beg > 0 && beg > RSTRING_LEN(str)) { + else if (beg > 0 && beg > blen) { return 0; } if (len == 0) { diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 24527a527f..f4ef6ccb6b 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -162,6 +162,15 @@ CODE assert_raise(ArgumentError) { "foo"[] } end + def test_AREF_underflow + require "rbconfig/sizeof" + assert_equal(nil, S("\u{3042 3044 3046}")[RbConfig::LIMITS["LONG_MIN"], 1]) + end + + def test_AREF_invalid_encoding + assert_equal(S("\x80"), S("A"*39+"\x80")[-1, 1]) + end + def test_ASET # '[]=' s = S("FooBar") s[0] = S('A') diff --git a/version.h b/version.h index bfe737dfe5..30cc09bf05 100644 --- a/version.h +++ b/version.h @@ -11,7 +11,7 @@ # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 6 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 240 +#define RUBY_PATCHLEVEL 241 #include "ruby/version.h" #include "ruby/internal/abi.h"