diff --git a/ChangeLog b/ChangeLog index 959b1286bf..48902b03b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Mon Apr 1 21:10:56 2013 Tanaka Akira + + * numeric.c (rb_num2ulong_internal): Don't cast a negative double value + into unsigned long, which is undefined behavior. + (rb_num2ull): Don't cast a value bigger than LLONG_MAX into + long long, which is undefined behavior. + Mon Apr 1 20:57:57 2013 Tanaka Akira * ext/-test-/num2int/num2int.c: Return string for result, instead of diff --git a/numeric.c b/numeric.c index a4eb0dd167..66820eeed1 100644 --- a/numeric.c +++ b/numeric.c @@ -2001,7 +2001,9 @@ rb_num2ulong_internal(VALUE val, int *wrap_p) double d = RFLOAT_VALUE(val); if (wrap_p) *wrap_p = d <= -1.0; /* NUM2ULONG(v) uses v.to_int conceptually. */ - return (unsigned long)d; + if (0 <= d) + return (unsigned long)d; + return (unsigned long)(long)d; } else { char buf[24]; @@ -2273,6 +2275,8 @@ rb_num2ull(VALUE val) case T_FLOAT: if (RFLOAT_VALUE(val) < ULLONG_MAX_PLUS_ONE && LLONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) { + if (0 <= RFLOAT_VALUE(val)) + return (unsigned LONG_LONG)(RFLOAT_VALUE(val)); return (unsigned LONG_LONG)(LONG_LONG)(RFLOAT_VALUE(val)); } else {