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

ruby-changes:28162

From: akr <ko1@a...>
Date: Wed, 10 Apr 2013 12:34:49 +0900 (JST)
Subject: [ruby-changes:28162] akr:r40214 (trunk): * bignum.c (rb_ll2big): Don't overflow on signed integer negation.

akr	2013-04-10 12:34:38 +0900 (Wed, 10 Apr 2013)

  New Revision: 40214

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

  Log:
    * bignum.c (rb_ll2big): Don't overflow on signed integer negation.
    
    * ext/bigdecimal/bigdecimal.c (MUL_OVERFLOW_SIGNED_VALUE_P): New
      macro.
      (AddExponent): Don't overflow on signed integer multiplication.
      (VpCtoV): Don't overflow on signed integer arithmetic.
      (VpCtoV): Don't overflow on signed integer arithmetic.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c
    trunk/ext/bigdecimal/bigdecimal.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 40213)
+++ ChangeLog	(revision 40214)
@@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Apr 10 12:32:37 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (rb_ll2big): Don't overflow on signed integer negation.
+
+	* ext/bigdecimal/bigdecimal.c (MUL_OVERFLOW_SIGNED_VALUE_P): New
+	  macro.
+	  (AddExponent): Don't overflow on signed integer multiplication.
+	  (VpCtoV): Don't overflow on signed integer arithmetic.
+	  (VpCtoV): Don't overflow on signed integer arithmetic.
+
 Wed Apr 10 06:32:12 2013  Tanaka Akira  <akr@f...>
 
 	* internal.h (MUL_OVERFLOW_INT_P): New macro.
Index: ext/bigdecimal/bigdecimal.c
===================================================================
--- ext/bigdecimal/bigdecimal.c	(revision 40213)
+++ ext/bigdecimal/bigdecimal.c	(revision 40214)
@@ -38,6 +38,16 @@ https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L38
 
 /* #define ENABLE_NUMERIC_STRING */
 
+#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 SIGNED_VALUE_MAX INTPTR_MAX
+#define SIGNED_VALUE_MIN INTPTR_MIN
+#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
+
 VALUE rb_cBigDecimal;
 VALUE rb_mBigMath;
 
@@ -3735,12 +3745,18 @@ AddExponent(Real *a, SIGNED_VALUE n) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L3745
     SIGNED_VALUE eb, mb;
     if (e > 0) {
 	if (n > 0) {
+            if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
+                MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
+                goto overflow;
 	    mb = m*(SIGNED_VALUE)BASE_FIG;
 	    eb = e*(SIGNED_VALUE)BASE_FIG;
 	    if (mb < eb) goto overflow;
 	}
     }
     else if (n < 0) {
+        if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
+            MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
+            goto underflow;
 	mb = m*(SIGNED_VALUE)BASE_FIG;
 	eb = e*(SIGNED_VALUE)BASE_FIG;
 	if (mb > eb) goto underflow;
@@ -5254,9 +5270,17 @@ VpCtoV(Real *a, const char *int_chr, siz https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L5270
 	    ++me;
 	}
 	while (i < me) {
+            if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
+                goto exp_overflow;
 	    es = e * (SIGNED_VALUE)BASE_FIG;
+            if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) ||
+                SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10)
+                goto exp_overflow;
 	    e = e * 10 + exp_chr[i] - '0';
+            if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
+                goto exp_overflow;
 	    if (es > (SIGNED_VALUE)(e * BASE_FIG)) {
+              exp_overflow:
 		exponent_overflow = 1;
 		e = es; /* keep sign */
 		break;
Index: bignum.c
===================================================================
--- bignum.c	(revision 40213)
+++ bignum.c	(revision 40214)
@@ -832,13 +832,17 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/bignum.c#L832
 rb_ll2big(LONG_LONG n)
 {
     long neg = 0;
+    unsigned LONG_LONG u;
     VALUE big;
 
     if (n < 0) {
-	n = -n;
+        u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
 	neg = 1;
     }
-    big = rb_ull2big(n);
+    else {
+        u = n;
+    }
+    big = rb_ull2big(u);
     if (neg) {
 	RBIGNUM_SET_SIGN(big, 0);
     }

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

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