fp_uscale.c: clamp parser underflow guard to POW10_MIN

mrb_read_float's underflow short-circuit used `final_p < -342 - nd`,
which for nd > 1 can be below POW10_MIN (-343). That let
parse_decimal call prescale() with a final_p below POW10_MIN, causing
an out-of-bounds read of pow10_tab. Tighten the guard to
`final_p < POW10_MIN`; values below that threshold cannot be
represented as a non-zero double for any mantissa within the parser's
19-digit cap.

Reported by OSS-Fuzz (testcase 6097379597287424).

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Yukihiro "Matz" Matsumoto
2026-05-13 12:01:46 +09:00
parent 27e14c16c4
commit 403b75fbeb
2 changed files with 10 additions and 1 deletions
+1 -1
View File
@@ -1497,7 +1497,7 @@ mrb_read_float(const char *str, char **endp, double *fp)
else if (final_p > 308) {
res = HUGE_VAL;
}
else if (final_p < -342 - nd) {
else if (final_p < POW10_MIN) {
res = 0.0;
}
else {
+9
View File
@@ -293,4 +293,13 @@ assert('Float#abs') do
assert_equal(0.0, f.abs)
end
assert('Float literal underflow') do
# Regression: float literals with exponents below POW10_MIN used to
# index pow10_tab out of bounds in mrb_read_float. They must round
# cleanly to 0.0.
assert_equal 0.0, 1.0e-400
assert_equal 0.0, 9.99e-344
assert_equal(-0.0, -92170141183460469231731687303715884105729e-383)
end
end # const_defined?(:Float)