summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--numeric.c6
2 files changed, 12 insertions, 1 deletions
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 <akr@fsij.org>
+
+ * 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 <akr@fsij.org>
* 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 {