mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
numeric.c: bounds-check float in Float#div before mrb_int cast
`Float#div(Integer)` cast its receiver to mrb_int unconditionally, which is undefined behavior when the float is outside the representable mrb_int range. ASan reports the UB on inputs like `5e+56.div(1)`. Reported by ClusterFuzz testcase clusterfuzz-testcase-minimized-mruby_fuzzer-5137605569347584. Guard the cast with FIXABLE_FLOAT and route over-range receivers to mrb_bint_div when MRB_USE_BIGINT is defined (matching flo_rounding_int's pattern), or raise via mrb_int_overflow when not. Existing `(float in range).div(int)` semantics are unchanged. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -351,6 +351,14 @@ flo_idiv(mrb_state *mrb, mrb_value xv)
|
||||
mrb_float x = mrb_float(xv);
|
||||
mrb_check_num_exact(mrb, x);
|
||||
mrb_int y = mrb_as_int(mrb, mrb_get_arg1(mrb));
|
||||
/* (mrb_int)x is UB when x is outside mrb_int range. */
|
||||
if (!FIXABLE_FLOAT(x)) {
|
||||
#ifdef MRB_USE_BIGINT
|
||||
return mrb_bint_div(mrb, mrb_bint_new_float(mrb, x), mrb_int_value(mrb, y));
|
||||
#else
|
||||
mrb_int_overflow(mrb, "div");
|
||||
#endif
|
||||
}
|
||||
return mrb_div_int_value(mrb, (mrb_int)x, y);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user