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

ruby-changes:8880

From: yugui <ko1@a...>
Date: Sun, 30 Nov 2008 18:25:23 +0900 (JST)
Subject: [ruby-changes:8880] Ruby:r20416 (ruby_1_9_1): merges r20359 from trunk into ruby_1_9_1.

yugui	2008-11-30 18:23:54 +0900 (Sun, 30 Nov 2008)

  New Revision: 20416

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

  Log:
    merges r20359 from trunk into ruby_1_9_1.
    * ext/bigdecimal/bigdecimal.c (VpAlloc): avoid ALLOCA_N() to avoid
      segmentation fault caused by (insanely) long decimal values.
      [ruby-dev:37189] fix #794
    * ext/bigdecimal/bigdecimal.c (BigDecimal_dump, BigDecimal_to_i,
      BigDecimal_to_f, BigDecimal_to_s, BigDecimal_split,
      BigDecimal_inspect): ditto.
    
    * ext/bigdecimal/bigdecimal.c (VpToString): small performance
      improvement.

  Modified files:
    branches/ruby_1_9_1/ChangeLog
    branches/ruby_1_9_1/ext/bigdecimal/bigdecimal.c
    branches/ruby_1_9_1/test/bigdecimal/test_bigdecimal.rb

Index: ruby_1_9_1/ChangeLog
===================================================================
--- ruby_1_9_1/ChangeLog	(revision 20415)
+++ ruby_1_9_1/ChangeLog	(revision 20416)
@@ -1,3 +1,16 @@
+Wed Nov 26 03:00:59 2008  Yukihiro Matsumoto  <matz@r...>
+
+	* ext/bigdecimal/bigdecimal.c (VpAlloc): avoid ALLOCA_N() to avoid
+	  segmentation fault caused by (insanely) long decimal values.
+	  [ruby-dev:37189] fix #794
+
+	* ext/bigdecimal/bigdecimal.c (BigDecimal_dump, BigDecimal_to_i,
+	  BigDecimal_to_f, BigDecimal_to_s, BigDecimal_split,
+	  BigDecimal_inspect): ditto.
+
+	* ext/bigdecimal/bigdecimal.c (VpToString): small performance
+	  improvement.
+
 Wed Nov 26 00:26:30 2008  Yukihiro Matsumoto  <matz@r...>
 
 	* strftime.c (STRFTIME): should add padding for %[xXrR] etc.
Index: ruby_1_9_1/ext/bigdecimal/bigdecimal.c
===================================================================
--- ruby_1_9_1/ext/bigdecimal/bigdecimal.c	(revision 20415)
+++ ruby_1_9_1/ext/bigdecimal/bigdecimal.c	(revision 20416)
@@ -309,17 +309,19 @@
 BigDecimal_dump(int argc, VALUE *argv, VALUE self)
 {
     ENTER(5);
-    char sz[50];
     Real *vp;
     char *psz;
     VALUE dummy;
+    volatile VALUE dump;
+
     rb_scan_args(argc, argv, "01", &dummy);
     GUARD_OBJ(vp,GetVpValue(self,1));
-    sprintf(sz,"%lu:",VpMaxPrec(vp)*VpBaseFig());
-    psz = ALLOCA_N(char,(unsigned int)VpNumOfChars(vp,"E")+strlen(sz));
-    sprintf(psz,"%s",sz);
+    dump = rb_str_new(0,VpNumOfChars(vp,"E")+50);
+    psz = RSTRING_PTR(dump);
+    sprintf(psz,"%lu:",VpMaxPrec(vp)*VpBaseFig());
     VpToString(vp, psz+strlen(psz), 0, 0);
-    return rb_str_new2(psz);
+    rb_str_resize(dump, strlen(psz));
+    return dump;
 }
 
 /*
@@ -529,6 +531,7 @@
     ENTER(5);
     int e,n,i,nf;
     U_LONG v,b,j;
+    volatile VALUE str;
     char *psz,*pch;
     Real *p;
 
@@ -536,14 +539,14 @@
 
     /* Infinity or NaN not converted. */
     if(VpIsNaN(p)) {
-       VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",0);
-       return Qnil;
+       VpException(VP_EXCEPTION_NaN,"Computation results to 'NaN'(Not a Number)",1);
+       return Qnil;		/* not reached */
     } else if(VpIsPosInf(p)) {
-       VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",0);
-       return Qnil;
+       VpException(VP_EXCEPTION_INFINITY,"Computation results to 'Infinity'",1);
+       return Qnil;		/* not reached */
     } else if(VpIsNegInf(p)) {
-       VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",0);
-       return Qnil;
+       VpException(VP_EXCEPTION_INFINITY,"Computation results to '-Infinity'",1);
+       return Qnil;		/* not reached */
     }
 
     e = VpExponent10(p);
@@ -553,7 +556,8 @@
         e = VpGetSign(p)*p->frac[0];
         return INT2FIX(e);
     }
-    psz = ALLOCA_N(char,(unsigned int)(e+nf+2));
+    str = rb_str_new(0, e+nf+2);
+    psz = RSTRING_PTR(str);
 
     n = (e+nf-1)/nf;
     pch = psz;
@@ -591,10 +595,12 @@
     double d;
     S_LONG e;
     char *buf;
+    volatile VALUE str;
 
     GUARD_OBJ(p,GetVpValue(self,1));
     if(VpVtoD(&d, &e, p)!=1) return rb_float_new(d);
-    buf = ALLOCA_N(char,(unsigned int)VpNumOfChars(p,"E"));
+    str = rb_str_new(0, VpNumOfChars(p,"E"));
+    buf = RSTRING_PTR(str);
     VpToString(p, buf, 0, 0);
     errno = 0;
     d = strtod(buf, 0);
@@ -1541,6 +1547,7 @@
     int   fmt=0;   /* 0:E format */
     int   fPlus=0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */
     Real  *vp;
+    volatile VALUE str;
     char  *psz;
     char   ch;
     U_LONG nc;
@@ -1577,14 +1584,16 @@
     }
     if(mc>0) nc += (nc + mc - 1) / mc + 1;
 
-    psz = ALLOCA_N(char,(unsigned int)nc);
+    str = rb_str_new(0, nc);
+    psz = RSTRING_PTR(str);
 
     if(fmt) {
         VpToFString(vp, psz, mc, fPlus);
     } else {
         VpToString (vp, psz, mc, fPlus);
     }
-    return rb_str_new2(psz);
+    rb_str_resize(str, strlen(psz));
+    return str;
 }
 
 /* Splits a BigDecimal number into four parts, returned as an array of values.
@@ -1616,24 +1625,29 @@
 {
     ENTER(5);
     Real *vp;
-    VALUE obj,obj1;
+    VALUE obj,str;
     S_LONG e;
     S_LONG s;
     char *psz1;
 
     GUARD_OBJ(vp,GetVpValue(self,1));
-    psz1 = ALLOCA_N(char,(unsigned int)VpNumOfChars(vp,"E"));
+    str = rb_str_new(0, VpNumOfChars(vp,"E"));
+    psz1 = RSTRING_PTR(str);
     VpSzMantissa(vp,psz1);
     s = 1;
     if(psz1[0]=='-') {
-        s = -1; ++psz1;
+	int len = strlen(psz1+1);
+
+	memmove(psz1, psz1+1, len);
+	psz1[len] = '\0';
+        s = -1;
     }
     if(psz1[0]=='N') s=0; /* NaN */
     e = VpExponent10(vp);
-    obj1 = rb_str_new2(psz1);
     obj  = rb_ary_new2(4);
     rb_ary_push(obj, INT2FIX(s));
-    rb_ary_push(obj, obj1);
+    rb_ary_push(obj, str);
+    rb_str_resize(str, strlen(psz1));
     rb_ary_push(obj, INT2FIX(10));
     rb_ary_push(obj, INT2NUM(e));
     return obj;
@@ -1666,20 +1680,22 @@
 {
     ENTER(5);
     Real *vp;
-    VALUE obj;
+    volatile VALUE obj;
     unsigned int nc;
-    char *psz1;
-    char *pszAll;
+    char *psz, *tmp;
 
     GUARD_OBJ(vp,GetVpValue(self,1));
     nc = VpNumOfChars(vp,"E");
     nc +=(nc + 9) / 10;
 
-    psz1   = ALLOCA_N(char,nc);
-    pszAll = ALLOCA_N(char,nc+256);
-    VpToString(vp, psz1, 10, 0);
-    sprintf(pszAll,"#<BigDecimal:%lx,'%s',%lu(%lu)>",self,psz1,VpPrec(vp)*VpBaseFig(),VpMaxPrec(vp)*VpBaseFig());
-    obj = rb_str_new2(pszAll);
+    obj = rb_str_new(0, nc+256);
+    psz = RSTRING_PTR(obj);
+    sprintf(psz,"#<BigDecimal:%lx,'",self);
+    tmp = psz + strlen(psz);
+    VpToString(vp, tmp, 10, 0);
+    tmp += strlen(tmp);
+    sprintf(tmp,"',%lu(%lu)>",VpPrec(vp)*VpBaseFig(),VpMaxPrec(vp)*VpBaseFig());
+    rb_str_resize(obj, strlen(psz));
     return obj;
 }
 
@@ -2534,6 +2550,7 @@
     int  sign=1;
     Real *vp = NULL;
     U_LONG mf = VpGetPrecLimit();
+    volatile VALUE buf;
 
     mx = (mx + BASE_FIG - 1) / BASE_FIG + 1;    /* Determine allocation unit. */
     if(szVal) {
@@ -2561,7 +2578,8 @@
 
     /* Skip all '_' after digit: 2006-6-30 */
     ni = 0;
-    psz = ALLOCA_N(char,strlen(szVal)+1);
+    buf = rb_str_new(0,strlen(szVal)+1);
+    psz = RSTRING_PTR(buf);
     i   = 0;
     ipn = 0;
     while((psz[i]=szVal[ipn])!=0) {
@@ -3656,7 +3674,7 @@
                 nc += fprintf(fp, "0.");
                 n = a->Prec;
                 for(i=0;i < n;++i) {
-                 m = BASE1;
+		    m = BASE1;
                     e = a->frac[i];
                     while(m) {
                         nn = e / m;
@@ -3838,7 +3856,7 @@
 /* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */
 {
     U_LONG i, ZeroSup;
-    U_LONG n, m, e, nn;
+    U_LONG n, e;
     char *pszSav = psz;
     S_LONG ex;
 
@@ -3854,18 +3872,12 @@
     *psz++ = '.';
     n = a->Prec;
     for(i=0;i < n;++i) {
-        m = BASE1;
         e = a->frac[i];
-        while(m) {
-            nn = e / m;
-            if((!ZeroSup) || nn) {
-                sprintf(psz, "%lu", nn);    /* The reading zero(s) */
-                psz += strlen(psz);
-                /* as 0.00xx will be ignored. */
-                ZeroSup = 0;    /* Set to print succeeding zeros */
-            }
-            e = e - nn * m;
-            m /= 10;
+	if((!ZeroSup) || e) {
+	    sprintf(psz, "%lu", e);    /* The reading zero(s) */
+	    psz += strlen(psz);
+	    /* as 0.00xx will be ignored. */
+	    ZeroSup = 0;    /* Set to print succeeding zeros */
         }
     }
     ex =(a->exponent) * BASE_FIG;
Index: ruby_1_9_1/test/bigdecimal/test_bigdecimal.rb
===================================================================
--- ruby_1_9_1/test/bigdecimal/test_bigdecimal.rb	(revision 20415)
+++ ruby_1_9_1/test/bigdecimal/test_bigdecimal.rb	(revision 20416)
@@ -303,9 +303,9 @@
     x = BigDecimal.new("0")
     assert_kind_of(Integer, x.to_i)
     assert_equal(0, x.to_i)
-    assert_nil(( 1 / x).to_i)
-    assert_nil((-1 / x).to_i)
-    assert_nil(( 0 / x).to_i)
+    assert_raise(FloatDomainError){( 1 / x).to_i}
+    assert_raise(FloatDomainError){(-1 / x).to_i}
+    assert_raise(FloatDomainError){( 0 / x).to_i}
     x = BigDecimal.new("1")
     assert_equal(1, x.to_i)
     x = BigDecimal.new((2**100).to_s)

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

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