mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #6781 from mruby/fix/sprintf-uaf
This commit is contained in:
@@ -380,6 +380,13 @@ mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fm
|
||||
argc++;
|
||||
argv--;
|
||||
mrb_ensure_string_type(mrb, fmt);
|
||||
/* Duplicate the format string so that to_s/inspect callbacks invoked
|
||||
during the loop cannot invalidate p/end by mutating the original
|
||||
via String#replace or similar. mrb_str_dup shares the underlying
|
||||
buffer, so this is O(1); String#replace on the original goes
|
||||
through str_replace which decrements the shared refcount, leaving
|
||||
our copy's buffer intact. */
|
||||
fmt = mrb_str_dup(mrb, fmt);
|
||||
p = RSTRING_PTR(fmt);
|
||||
end = p + RSTRING_LEN(fmt);
|
||||
blen = 0;
|
||||
|
||||
@@ -90,3 +90,19 @@ assert("String#% invalid format") do
|
||||
"%?" % ""
|
||||
end
|
||||
end
|
||||
|
||||
assert("sprintf with to_s mutating format string") do
|
||||
# The to_s callback must not be able to invalidate sprintf's internal
|
||||
# iteration pointers by mutating the format string.
|
||||
fmt = "%s" + "B" * 200
|
||||
mutator = Object.new
|
||||
$sprintf_test_fmt = fmt
|
||||
def mutator.to_s
|
||||
$sprintf_test_fmt.replace("Z")
|
||||
"ok"
|
||||
end
|
||||
result = sprintf(fmt, mutator)
|
||||
assert_equal 202, result.length
|
||||
assert_equal "ok", result[0, 2]
|
||||
assert_equal "B" * 200, result[2..]
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user