mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #6780 from mruby/fix/string-prepend-overflow
This commit is contained in:
@@ -2201,15 +2201,27 @@ str_prepend(mrb_state *mrb, mrb_value self)
|
||||
|
||||
char *p = RSTRING_PTR(self);
|
||||
|
||||
/* Move original content to the end */
|
||||
/* Move original content to the end. The original self data now lives
|
||||
at p + total_prepend_len, which we use as the source for any
|
||||
self-referencing arguments (e.g., s.prepend(s, s)) to avoid reading
|
||||
data that has already been overwritten by earlier copies. */
|
||||
memmove(p + total_prepend_len, p, self_len);
|
||||
|
||||
/* Copy prepended strings in order */
|
||||
mrb_int offset = 0;
|
||||
for (mrb_int i = 0; i < argc; i++) {
|
||||
mrb_int arg_len = RSTRING_LEN(argv[i]);
|
||||
const char *src;
|
||||
mrb_int arg_len;
|
||||
if (mrb_obj_eq(mrb, self, argv[i])) {
|
||||
src = p + total_prepend_len;
|
||||
arg_len = self_len;
|
||||
}
|
||||
else {
|
||||
src = RSTRING_PTR(argv[i]);
|
||||
arg_len = RSTRING_LEN(argv[i]);
|
||||
}
|
||||
if (arg_len > 0) {
|
||||
memcpy(p + offset, RSTRING_PTR(argv[i]), arg_len);
|
||||
memcpy(p + offset, src, arg_len);
|
||||
offset += arg_len;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,6 +492,21 @@ assert('String#prepend') do
|
||||
g = "world"
|
||||
assert_equal "hello world", g.prepend("", "hello ", "")
|
||||
assert_equal "hello world", g
|
||||
|
||||
# Self-referencing arguments (GHSA-3hgj-g76g-878c)
|
||||
h = "A" * 100
|
||||
h.prepend(h, h)
|
||||
assert_equal 300, h.length
|
||||
assert_equal "A" * 300, h
|
||||
|
||||
# Mixed self-reference and literal
|
||||
i = "AB"
|
||||
i.prepend("XYZ", i)
|
||||
assert_equal "XYZABAB", i
|
||||
|
||||
j = "AB"
|
||||
j.prepend(j, "X", j)
|
||||
assert_equal "ABXABAB", j
|
||||
end
|
||||
|
||||
assert('String#ljust') do
|
||||
|
||||
Reference in New Issue
Block a user