mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #5986 from dearblue/bytesplice
Fix bugs in `String#bytesplice`
This commit is contained in:
+15
-5
@@ -2947,16 +2947,25 @@ 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");
|
||||
}
|
||||
if (RSTR_LEN(s) <= idx1+len1) {
|
||||
if (len1 < 0 || len2 < 0) {
|
||||
mrb_raise(mrb, E_INDEX_ERROR, "negative length");
|
||||
}
|
||||
mrb_int n;
|
||||
if (mrb_int_add_overflow(idx1, len1, &n) || RSTR_LEN(s) < n) {
|
||||
len1 = RSTR_LEN(s) - idx1;
|
||||
}
|
||||
if (RSTRING_LEN(replace) <= idx2+len2) {
|
||||
if (mrb_int_add_overflow(idx2, len2, &n) || RSTRING_LEN(replace) < n) {
|
||||
len2 = RSTRING_LEN(replace) - idx2;
|
||||
}
|
||||
if (len2 == 0) return replace;
|
||||
mrb_str_modify(mrb, s);
|
||||
if (len1 >= len2) {
|
||||
memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
|
||||
@@ -2971,7 +2980,7 @@ str_bytesplice(mrb_state *mrb, mrb_value str, mrb_int idx1, mrb_int len1, mrb_va
|
||||
memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, slen-(idx1+len1));
|
||||
memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
|
||||
}
|
||||
return replace;
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3006,6 +3015,7 @@ mrb_str_bytesplice(mrb_state *mrb, mrb_value str)
|
||||
mrb_get_args(mrb, "iiS", &idx1, &len1, &replace);
|
||||
return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
|
||||
}
|
||||
mrb_ensure_string_type(mrb, replace);
|
||||
if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) != MRB_RANGE_OK) break;
|
||||
if (mrb_range_beg_len(mrb, range2, &idx2, &len2, RSTRING_LEN(replace), FALSE) != MRB_RANGE_OK) break;
|
||||
return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
|
||||
|
||||
+30
-24
@@ -902,62 +902,68 @@ end
|
||||
assert('String#bytesplice') do
|
||||
# range, replace (len1=len2)
|
||||
a = "0123456789"
|
||||
assert_equal "ab", a.bytesplice(1..2, "ab")
|
||||
assert_equal "0ab3456789", a
|
||||
assert_equal "0ab3456789", a.bytesplice(1..2, "ab")
|
||||
|
||||
# range, replace (len1>len2)
|
||||
a = "0123456789"
|
||||
assert_equal "ab", a.bytesplice(1..3, "ab")
|
||||
assert_equal "0ab456789", a
|
||||
assert_equal "0ab456789", a.bytesplice(1..3, "ab")
|
||||
|
||||
# range, replace (len1<len2)
|
||||
a = "0123456789"
|
||||
assert_equal "ab", a.bytesplice(1..1, "ab")
|
||||
assert_equal "0ab23456789", a
|
||||
assert_equal "0ab23456789", a.bytesplice(1..1, "ab")
|
||||
|
||||
# idx, len, replace (len1=len2)
|
||||
a = "0123456789"
|
||||
assert_equal "ab", a.bytesplice(1, 2, "ab")
|
||||
assert_equal "0ab3456789", a
|
||||
assert_equal "0ab3456789", a.bytesplice(1, 2, "ab")
|
||||
|
||||
# idx, len, replace (len1>len2)
|
||||
a = "0123456789"
|
||||
assert_equal "ab", a.bytesplice(1, 3, "ab")
|
||||
assert_equal "0ab456789", a
|
||||
assert_equal "0ab456789", a.bytesplice(1, 3, "ab")
|
||||
|
||||
# idx, len, replace (len1<len2)
|
||||
a = "0123456789"
|
||||
assert_equal "ab", a.bytesplice(1, 1, "ab")
|
||||
assert_equal "0ab23456789", a
|
||||
assert_equal "0ab23456789", a.bytesplice(1, 1, "ab")
|
||||
|
||||
b = "abcdefg"
|
||||
# range, replace, range (len1=len2)
|
||||
a = "0123456789"
|
||||
assert_equal b, a.bytesplice(1..2, b, 0..1)
|
||||
assert_equal "0ab3456789", a
|
||||
assert_equal "0ab3456789", a.bytesplice(1..2, b, 0..1)
|
||||
|
||||
# range, replace, range (len1>len2)
|
||||
a = "0123456789"
|
||||
assert_equal b, a.bytesplice(1..3, b, 1..2)
|
||||
assert_equal "0bc456789", a
|
||||
assert_equal "0bc456789", a.bytesplice(1..3, b, 1..2)
|
||||
|
||||
# range, replace, range (len1<len2)
|
||||
a = "0123456789"
|
||||
assert_equal b, a.bytesplice(1..1, b, 2..3)
|
||||
assert_equal "0cd23456789", a
|
||||
assert_equal "0cd23456789", a.bytesplice(1..1, b, 2..3)
|
||||
|
||||
# idx, len, replace, idx, len (len1=len2)
|
||||
a = "0123456789"
|
||||
assert_equal b, a.bytesplice(1, 2, b, 0, 2)
|
||||
assert_equal "0ab3456789", a
|
||||
assert_equal "0ab3456789", a.bytesplice(1, 2, b, 0, 2)
|
||||
|
||||
# idx, len, replace, idx, len (len1>len2)
|
||||
a = "0123456789"
|
||||
assert_equal b, a.bytesplice(1, 3, b, 1, 2)
|
||||
assert_equal "0bc456789", a
|
||||
assert_equal "0bc456789", a.bytesplice(1, 3, b, 1, 2)
|
||||
|
||||
# idx, len, replace, idx, len (len1<len2)
|
||||
a = "0123456789"
|
||||
assert_equal b, a.bytesplice(1, 1, b, 2, 2)
|
||||
assert_equal "0cd23456789", a
|
||||
assert_equal "0cd23456789", a.bytesplice(1, 1, b, 2, 2)
|
||||
|
||||
# check the object type to replace
|
||||
assert_raise(TypeError) { "0123456789".bytesplice(1, 1, Object.new) }
|
||||
|
||||
# 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") }
|
||||
|
||||
# check the negative length
|
||||
assert_raise(IndexError) { "0123456789".bytesplice(3, -4, "ab") }
|
||||
|
||||
# with an empty string
|
||||
assert_equal "012789", "0123456789".bytesplice(3, 4, "")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user