Skip to content

Commit

Permalink
merge revision(s) 23610:23613:
Browse files Browse the repository at this point in the history
	* ext/bigdecimal/bigdecimal.c (VpAlloc): avoid ALLOCA_N() to avoid
	  segmentation fault caused by (insanely) long decimal values.
	  backported from 1.9.
	* ext/bigdecimal/bigdecimal.c (BigDecimal_dump, BigDecimal_to_i,
	  BigDecimal_to_f, BigDecimal_to_s, BigDecimal_split,
	  BigDecimal_inspect): ditto.
	* ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): returns Inf if
	  exp is bigger than DBL_MANT_DIG.


git-svn-id: http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_8_7@23645 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
shyouhei committed Jun 7, 2009
1 parent afd72f5 commit a7fe799
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 48 deletions.
15 changes: 15 additions & 0 deletions ChangeLog
@@ -1,3 +1,18 @@
Mon Jun 8 08:15:36 2009 Yukihiro Matsumoto <matz@ruby-lang.org>

* ext/bigdecimal/bigdecimal.c (VpAlloc): avoid ALLOCA_N() to avoid
segmentation fault caused by (insanely) long decimal values.
backported from 1.9. CVE-2009-1904

* ext/bigdecimal/bigdecimal.c (BigDecimal_dump, BigDecimal_to_i,
BigDecimal_to_f, BigDecimal_to_s, BigDecimal_split,
BigDecimal_inspect): ditto.

Mon Jun 8 08:15:36 2009 Yukihiro Matsumoto <matz@ruby-lang.org>

* ext/bigdecimal/bigdecimal.c (BigDecimal_to_f): returns Inf if
exp is bigger than DBL_MANT_DIG.

Wed Jun 3 21:16:30 2009 Tanaka Akira <akr@fsij.org>

* file.c: include fcntl.h for O_RDONLY on Solaris.
Expand Down
102 changes: 58 additions & 44 deletions ext/bigdecimal/bigdecimal.c
Expand Up @@ -306,17 +306,19 @@ static VALUE
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;
}

/*
Expand Down Expand Up @@ -520,21 +522,22 @@ BigDecimal_to_i(VALUE self)
ENTER(5);
int e,n,i,nf;
U_LONG v,b,j;
volatile VALUE str;
char *psz,*pch;
Real *p;

GUARD_OBJ(p,GetVpValue(self,1));

/* 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);
Expand All @@ -544,7 +547,8 @@ BigDecimal_to_i(VALUE self)
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;
Expand Down Expand Up @@ -589,17 +593,21 @@ BigDecimal_to_f(VALUE self)
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"));
if (e > DBL_MAX_10_EXP) goto erange;
str = rb_str_new(0, VpNumOfChars(p,"E"));
buf = RSTRING_PTR(str);
VpToString(p, buf, 0, 0);
errno = 0;
d = strtod(buf, 0);
if(errno == ERANGE) {
erange:
VpException(VP_EXCEPTION_OVERFLOW,"BigDecimal to Float conversion",0);
if(d>0.0) return rb_float_new(DBL_MAX);
else return rb_float_new(-DBL_MAX);
if(d>0.0) d = VpGetDoublePosInf();
else d = VpGetDoubleNegInf();
}
return rb_float_new(d);
}
Expand Down Expand Up @@ -1491,6 +1499,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
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;
Expand Down Expand Up @@ -1527,14 +1536,16 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
}
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.
Expand Down Expand Up @@ -1566,24 +1577,29 @@ BigDecimal_split(VALUE self)
{
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;
Expand Down Expand Up @@ -1616,20 +1632,22 @@ BigDecimal_inspect(VALUE self)
{
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;
}

Expand Down Expand Up @@ -2482,6 +2500,7 @@ VpAlloc(U_LONG mx, const char *szVal)
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) {
Expand Down Expand Up @@ -2509,7 +2528,8 @@ VpAlloc(U_LONG mx, const char *szVal)

/* 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) {
Expand Down Expand Up @@ -3601,7 +3621,7 @@ VPrint(FILE *fp, char *cntl_chr, Real *a)
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;
Expand Down Expand Up @@ -3783,7 +3803,7 @@ VpToString(Real *a,char *psz,int fFmt,int fPlus)
/* 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;

Expand All @@ -3799,18 +3819,12 @@ VpToString(Real *a,char *psz,int fFmt,int fPlus)
*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;
Expand Down
8 changes: 4 additions & 4 deletions version.h
@@ -1,15 +1,15 @@
#define RUBY_VERSION "1.8.7"
#define RUBY_RELEASE_DATE "2009-06-03"
#define RUBY_RELEASE_DATE "2009-06-08"
#define RUBY_VERSION_CODE 187
#define RUBY_RELEASE_CODE 20090603
#define RUBY_PATCHLEVEL 171
#define RUBY_RELEASE_CODE 20090608
#define RUBY_PATCHLEVEL 172

#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
#define RUBY_VERSION_TEENY 7
#define RUBY_RELEASE_YEAR 2009
#define RUBY_RELEASE_MONTH 6
#define RUBY_RELEASE_DAY 3
#define RUBY_RELEASE_DAY 8

#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];
Expand Down

0 comments on commit a7fe799

Please sign in to comment.