[前][次][番号順一覧][スレッド一覧]

ruby-changes:28156

From: akr <ko1@a...>
Date: Tue, 9 Apr 2013 20:40:08 +0900 (JST)
Subject: [ruby-changes:28156] akr:r40208 (trunk): * internal.h (MUL_OVERFLOW_SIGNED_INTEGER_P): New macro.

akr	2013-04-09 20:39:53 +0900 (Tue, 09 Apr 2013)

  New Revision: 40208

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=40208

  Log:
    * internal.h (MUL_OVERFLOW_SIGNED_INTEGER_P): New macro.
      (MUL_OVERFLOW_FIXNUM_P): Ditto.
      (MUL_OVERFLOW_LONG_P): Ditto.
    
    * array.c (rb_ary_product): Don't overflow on signed integer
      multiplication.
    
    * numeric.c (fix_mul): Ditto.
      (int_pow): Ditto.
    
    * rational.c (f_imul): Ditto.
    
    * insns.def (opt_mult): Ditto.
    
    * thread.c (sleep_timeval): Don't overflow on signed integer addition.
    
    * bignum.c (rb_int2big): Don't overflow on signed integer negation.
      (rb_big2ulong): Ditto.
      (rb_big2long): Ditto.
      (rb_big2ull): Ditto.
      (rb_big2ll): Ditto.

  Modified files:
    trunk/ChangeLog
    trunk/array.c
    trunk/bignum.c
    trunk/insns.def
    trunk/internal.h
    trunk/numeric.c
    trunk/rational.c
    trunk/thread.c

Index: array.c
===================================================================
--- array.c	(revision 40207)
+++ array.c	(revision 40208)
@@ -5034,15 +5034,14 @@ rb_ary_product(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/array.c#L5034
     else {
 	/* Compute the length of the result array; return [] if any is empty */
 	for (i = 0; i < n; i++) {
-	    long k = RARRAY_LEN(arrays[i]), l = resultlen;
+	    long k = RARRAY_LEN(arrays[i]);
 	    if (k == 0) {
 		result = rb_ary_new2(0);
 		goto done;
 	    }
-	    resultlen *= k;
-	    if (resultlen < k || resultlen < l || resultlen / k != l) {
+            if (MUL_OVERFLOW_LONG_P(resultlen, k))
 		rb_raise(rb_eRangeError, "too big to product");
-	    }
+	    resultlen *= k;
 	}
 	result = rb_ary_new2(resultlen);
     }
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 40207)
+++ ChangeLog	(revision 40208)
@@ -1,3 +1,27 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Apr  9 20:38:20 2013  Tanaka Akira  <akr@f...>
+
+	* internal.h (MUL_OVERFLOW_SIGNED_INTEGER_P): New macro.
+	  (MUL_OVERFLOW_FIXNUM_P): Ditto.
+	  (MUL_OVERFLOW_LONG_P): Ditto.
+
+	* array.c (rb_ary_product): Don't overflow on signed integer
+	  multiplication.
+
+	* numeric.c (fix_mul): Ditto.
+	  (int_pow): Ditto.
+
+	* rational.c (f_imul): Ditto.
+
+	* insns.def (opt_mult): Ditto.
+
+	* thread.c (sleep_timeval): Don't overflow on signed integer addition.
+
+	* bignum.c (rb_int2big): Don't overflow on signed integer negation.
+	  (rb_big2ulong): Ditto.
+	  (rb_big2long): Ditto.
+	  (rb_big2ull): Ditto.
+	  (rb_big2ll): Ditto.
+
 Tue Apr  9 19:45:44 2013  Tanaka Akira  <akr@f...>
 
 	* lib/open-uri.rb: Support multiple fields with same field
Index: insns.def
===================================================================
--- insns.def	(revision 40207)
+++ insns.def	(revision 40208)
@@ -1418,16 +1418,13 @@ opt_mult https://github.com/ruby/ruby/blob/trunk/insns.def#L1418
 	    val = recv;
 	}
 	else {
-	    volatile long c;
 	    b = FIX2LONG(obj);
-	    c = a * b;
-
-	    if (FIXABLE(c) && c / a == b) {
-		val = LONG2FIX(c);
-	    }
-	    else {
+            if (MUL_OVERFLOW_FIXNUM_P(a, b)) {
 		val = rb_big_mul(rb_int2big(a), rb_int2big(b));
-	    }
+            }
+            else {
+		val = LONG2FIX(a * b);
+            }
 	}
     }
     else if (FLONUM_2_P(recv, obj) &&
Index: thread.c
===================================================================
--- thread.c	(revision 40207)
+++ thread.c	(revision 40208)
@@ -994,10 +994,17 @@ sleep_timeval(rb_thread_t *th, struct ti https://github.com/ruby/ruby/blob/trunk/thread.c#L994
     enum rb_thread_status prev_status = th->status;
 
     getclockofday(&to);
-    to.tv_sec += tv.tv_sec;
+    if (TIMET_MAX - tv.tv_sec < to.tv_sec)
+        to.tv_sec = TIMET_MAX;
+    else
+        to.tv_sec += tv.tv_sec;
     if ((to.tv_usec += tv.tv_usec) >= 1000000) {
-	to.tv_sec++;
-	to.tv_usec -= 1000000;
+        if (to.tv_sec == TIMET_MAX)
+            to.tv_usec = 999999;
+        else {
+            to.tv_sec++;
+            to.tv_usec -= 1000000;
+        }
     }
 
     th->status = THREAD_STOPPED;
Index: numeric.c
===================================================================
--- numeric.c	(revision 40207)
+++ numeric.c	(revision 40208)
@@ -2731,7 +2731,6 @@ fix_mul(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2731
 #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
 	LONG_LONG d;
 #else
-	volatile long c;
 	VALUE r;
 #endif
 
@@ -2745,13 +2744,11 @@ fix_mul(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2744
 #else
 	if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
 	    return LONG2FIX(a*b);
-	c = a * b;
-	r = LONG2FIX(c);
-
 	if (a == 0) return x;
-	if (FIX2LONG(r) != c || c/a != b) {
+        if (MUL_OVERFLOW_FIXNUM_P(a, b))
 	    r = rb_big_mul(rb_int2big(a), rb_int2big(b));
-	}
+        else
+            r = LONG2FIX(a * b);
 	return r;
 #endif
     }
@@ -2973,11 +2970,10 @@ int_pow(long x, unsigned long y) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2970
 	    y >>= 1;
 	}
 	{
-	    volatile long xz = x * z;
-	    if (!POSFIXABLE(xz) || xz / x != z) {
+            if (MUL_OVERFLOW_FIXNUM_P(x, z)) {
 		goto bignum;
 	    }
-	    z = xz;
+	    z = x * z;
 	}
     } while (--y);
     if (neg) z = -z;
Index: internal.h
===================================================================
--- internal.h	(revision 40207)
+++ internal.h	(revision 40208)
@@ -28,6 +28,15 @@ extern "C" { https://github.com/ruby/ruby/blob/trunk/internal.h#L28
 #endif
 #define TIMET_MAX_PLUS_ONE (2*(double)(TIMET_MAX/2+1))
 
+#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+    (a) == 0 ? 0 : \
+    (a) == -1 ? (b) < -(max) : \
+    (a) > 0 ? \
+      ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
+      ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
+#define MUL_OVERFLOW_FIXNUM_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+
 struct rb_deprecated_classext_struct {
     char conflict[sizeof(VALUE) * 3];
 };
Index: bignum.c
===================================================================
--- bignum.c	(revision 40207)
+++ bignum.c	(revision 40208)
@@ -309,13 +309,17 @@ VALUE https://github.com/ruby/ruby/blob/trunk/bignum.c#L309
 rb_int2big(SIGNED_VALUE n)
 {
     long neg = 0;
+    VALUE u;
     VALUE big;
 
     if (n < 0) {
-	n = -n;
+        u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
 	neg = 1;
     }
-    big = rb_uint2big(n);
+    else {
+        u = n;
+    }
+    big = rb_uint2big(u);
     if (neg) {
 	RBIGNUM_SET_SIGN(big, 0);
     }
@@ -1224,12 +1228,15 @@ rb_big2ulong(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L1228
 {
     VALUE num = big2ulong(x, "unsigned long", TRUE);
 
-    if (!RBIGNUM_SIGN(x)) {
-	unsigned long v = (unsigned long)(-(long)num);
-
-	if (v <= LONG_MAX)
-	    rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
-	return (VALUE)v;
+    if (RBIGNUM_POSITIVE_P(x)) {
+        return num;
+    }
+    else {
+        if (num <= LONG_MAX)
+            return -(long)num;
+        if (num == 1+(unsigned long)(-(LONG_MIN+1)))
+            return LONG_MIN;
+        rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
     }
     return num;
 }
@@ -1239,12 +1246,18 @@ rb_big2long(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L1246
 {
     VALUE num = big2ulong(x, "long", TRUE);
 
-    if ((long)num < 0 &&
-	(RBIGNUM_SIGN(x) || (long)num != LONG_MIN)) {
-	rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
+    if (RBIGNUM_POSITIVE_P(x)) {
+        if (LONG_MAX < num)
+            rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
+        return num;
+    }
+    else {
+        if (num <= LONG_MAX)
+            return -(long)num;
+        if (num == 1+(unsigned long)(-(LONG_MIN+1)))
+            return LONG_MIN;
+        rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
     }
-    if (!RBIGNUM_SIGN(x)) return -(SIGNED_VALUE)num;
-    return num;
 }
 
 #if HAVE_LONG_LONG
@@ -1272,13 +1285,15 @@ rb_big2ull(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L1285
 {
     unsigned LONG_LONG num = big2ull(x, "unsigned long long");
 
-    if (!RBIGNUM_SIGN(x)) {
-	LONG_LONG v = -(LONG_LONG)num;
-
-	/* FIXNUM_MIN-1 .. LLONG_MIN mapped into 0xbfffffffffffffff .. LONG_MAX+1 */
-	if ((unsigned LONG_LONG)v <= LLONG_MAX)
-	    rb_raise(rb_eRangeError, "bignum out of range of unsigned long long");
-	return v;
+    if (RBIGNUM_POSITIVE_P(x)) {
+        return num;
+    }
+    else {
+        if (num <= LLONG_MAX)
+            return -(LONG_LONG)num;
+        if (num == 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
+            return LLONG_MIN;
+        rb_raise(rb_eRangeError, "bignum out of range of unsigned long long");
     }
     return num;
 }
@@ -1288,12 +1303,18 @@ rb_big2ll(VALUE x) https://github.com/ruby/ruby/blob/trunk/bignum.c#L1303
 {
     unsigned LONG_LONG num = big2ull(x, "long long");
 
-    if ((LONG_LONG)num < 0 && (RBIGNUM_SIGN(x)
-			       || (LONG_LONG)num != LLONG_MIN)) {
-	rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
+    if (RBIGNUM_POSITIVE_P(x)) {
+        if (LLONG_MAX < num)
+            rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
+        return num;
+    }
+    else {
+        if (num <= LLONG_MAX)
+            return -(LONG_LONG)num;
+        if (num == 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
+            return LLONG_MIN;
+        rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
     }
-    if (!RBIGNUM_SIGN(x)) return -(LONG_LONG)num;
-    return num;
 }
 
 #endif  /* HAVE_LONG_LONG */
Index: rational.c
===================================================================
--- rational.c	(revision 40207)
+++ rational.c	(revision 40208)
@@ -639,7 +639,6 @@ inline static VALUE https://github.com/ruby/ruby/blob/trunk/rational.c#L639
 f_imul(long a, long b)
 {
     VALUE r;
-    volatile long c;
 
     if (a == 0 || b == 0)
 	return ZERO;
@@ -648,10 +647,10 @@ f_imul(long a, long b) https://github.com/ruby/ruby/blob/trunk/rational.c#L647
     else if (b == 1)
 	return LONG2NUM(a);
 
-    c = a * b;
-    r = LONG2NUM(c);
-    if (NUM2LONG(r) != c || (c / a) != b)
+    if (MUL_OVERFLOW_LONG_P(a, b))
 	r = rb_big_mul(rb_int2big(a), rb_int2big(b));
+    else
+        r = LONG2NUM(a * b);
     return r;
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]