From 5bc3a48ecbe02a4a8249f0aeef1d2cfd99a27701 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sat, 15 Apr 2023 21:25:59 +0900 Subject: [PATCH] Handling negative indices in `String#bytesplice` --- src/string.c | 8 +++++++- test/t/string.rb | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/string.c b/src/string.c index 966d7c8c9..c191fcbb7 100644 --- a/src/string.c +++ b/src/string.c @@ -2947,7 +2947,13 @@ static mrb_value str_bytesplice(mrb_state *mrb, mrb_value str, mrb_int idx1, mrb_int len1, mrb_value replace, mrb_int idx2, mrb_int len2) { struct RString *s = RSTRING(str); - if (RSTR_LEN(s) < idx1 || RSTRING_LEN(replace) < idx2) { + if (idx1 < 0) { + idx1 += RSTR_LEN(s); + } + if (idx2 < 0) { + idx2 += RSTRING_LEN(replace); + } + if (RSTR_LEN(s) < idx1 || idx1 < 0 || RSTRING_LEN(replace) < idx2 || idx2 < 0) { mrb_raise(mrb, E_INDEX_ERROR, "index out of string"); } mrb_int n; diff --git a/test/t/string.rb b/test/t/string.rb index 5fe0761f6..0b9916b59 100644 --- a/test/t/string.rb +++ b/test/t/string.rb @@ -955,4 +955,9 @@ assert('String#bytesplice') do # check the overflow to index and length (to be pass without crash) assert_nothing_raised { "0123456789".bytesplice(8, ~(-1 << 31), "ab") } # for MRB_INT32 assert_nothing_raised { begin; "0123456789".bytesplice(8, ~(-1 << 63), "ab"); rescue ArgumentError, RangeError; end } # for MRB_INT64 + + # check the negative index + assert_equal "0ab3456789", "0123456789".bytesplice(-9, 2, "ab") + assert_equal "ab23456789", "0123456789".bytesplice(-10, 2, "ab") + assert_raise(IndexError) { "0123456789".bytesplice(-11, 2, "ab") } end