mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
fp_uscale.c: clamp precision in %g to avoid OOB in fixed_width
When sprintf is called with a precision larger than the double's significand width (e.g. "%.51g"), fixed_width() indexed pow10 tables out of bounds and produced a negative shift exponent. Cap the internal digit count to 18 in the %g branch, matching the existing %e and %f branches; downstream loops already zero-pad to the caller's precision so visible output is unchanged. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,16 @@ assert("String#% invalid format") do
|
||||
end
|
||||
end
|
||||
|
||||
assert("sprintf %g with high precision") do
|
||||
# Regression test: precision values larger than double's significand
|
||||
# used to cause out-of-bounds reads in fp_uscale's fixed_width().
|
||||
assert_equal "7", "%.*g" % [51, 7]
|
||||
assert_equal "7.5", "%.*g" % [51, 7.5]
|
||||
assert_equal "7", "%.51g" % 7.0
|
||||
assert_equal "7." + "0" * 50, "%#.51g" % 7.0
|
||||
assert_equal "7", "%.*g" % [1000, 7.0]
|
||||
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.
|
||||
|
||||
+4
-2
@@ -1247,8 +1247,10 @@ mrb_format_float(mrb_float f, char *buf, size_t buf_size, char fmt, int prec, ch
|
||||
}
|
||||
else if (fmt == 'g') {
|
||||
/* g/G format */
|
||||
int fprec;
|
||||
fixed_width((double)f, prec, &d, &p);
|
||||
int fprec, n = prec;
|
||||
if (n > 18) n = 18;
|
||||
if (n < 1) n = 1;
|
||||
fixed_width((double)f, n, &d, &p);
|
||||
nd = count_digits(d);
|
||||
exp = p + nd - 1;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user