merge revision(s) 42908,42918: [Backport #8864]

test_sprintf_comb.rb: split tests

	* test/ruby/test_sprintf_comb.rb (test_format_integer),
  (test_format_float): split huge tests by the formats.
	* vsnprintf.c (MAXEXP, MAXFRACT): calculate depending on constants in
	  float.h.

	* vsnprintf.c (BSD_vfprintf): limit length for cvt() to get rid of
	  buffer overflow.  [ruby-core:57023] [Bug #8864]

	* vsnprintf.c (exponent): make expbuf size more precise.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@42944 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagachika 2013-09-15 13:51:27 +00:00
parent b3571b5597
commit 64eeb5f302
4 changed files with 61 additions and 35 deletions

View file

@ -1,3 +1,13 @@
Sun Sep 15 22:03:01 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* vsnprintf.c (MAXEXP, MAXFRACT): calculate depending on constants in
float.h.
* vsnprintf.c (BSD_vfprintf): limit length for cvt() to get rid of
buffer overflow. [ruby-core:57023] [Bug #8864]
* vsnprintf.c (exponent): make expbuf size more precise.
Sat Sep 14 00:01:20 2013 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org> Sat Sep 14 00:01:20 2013 CHIKANAGA Tomoyuki <nagachika@ruby-lang.org>
* lib/rubygems: Update to RubyGems to 2.0.8. [ruby-core:57155] * lib/rubygems: Update to RubyGems to 2.0.8. [ruby-core:57155]

View file

@ -107,7 +107,9 @@ class TestSprintfComb < Test::Unit::TestCase
] ]
VS.reverse! VS.reverse!
def combination(*args, &b) FLAGS = [['', ' '], ['', '#'], ['', '+'], ['', '-'], ['', '0']]
def self.combination(*args, &b)
#AllPairs.exhaustive_each(*args, &b) #AllPairs.exhaustive_each(*args, &b)
AllPairs.each(*args, &b) AllPairs.each(*args, &b)
end end
@ -268,17 +270,8 @@ class TestSprintfComb < Test::Unit::TestCase
str str
end end
def test_format_integer def self.assertions_format_integer(format)
combination( proc {
%w[B b d o X x],
[nil, 0, 5, 20],
["", ".", ".0", ".8", ".20"],
['', ' '],
['', '#'],
['', '+'],
['', '-'],
['', '0']) {|type, width, precision, sp, hs, pl, mi, zr|
format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
VS.each {|v| VS.each {|v|
r = sprintf format, v r = sprintf format, v
e = emu_int format, v e = emu_int format, v
@ -293,6 +286,14 @@ class TestSprintfComb < Test::Unit::TestCase
} }
end end
combination(%w[B b d o X x],
[nil, 0, 5, 20],
["", ".", ".0", ".8", ".20"],
*FLAGS) {|type, width, precision, sp, hs, pl, mi, zr|
format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
define_method("test_format_integer(#{format})", assertions_format_integer(format))
}
FLOAT_VALUES = [ FLOAT_VALUES = [
-1e100, -1e100,
-123456789.0, -123456789.0,
@ -526,17 +527,8 @@ class TestSprintfComb < Test::Unit::TestCase
end end
def test_format_float def self.assertions_format_float(format)
combination( proc {
%w[e E f g G],
[nil, 0, 5, 20],
["", ".", ".0", ".8", ".20", ".200"],
['', ' '],
['', '#'],
['', '+'],
['', '-'],
['', '0']) {|type, width, precision, sp, hs, pl, mi, zr|
format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
FLOAT_VALUES.each {|v| FLOAT_VALUES.each {|v|
r = sprintf format, v r = sprintf format, v
e = emu_float format, v e = emu_float format, v
@ -550,4 +542,12 @@ class TestSprintfComb < Test::Unit::TestCase
} }
} }
end end
combination(%w[e E f g G],
[nil, 0, 5, 20],
["", ".", ".0", ".8", ".20", ".200", ".9999"],
*FLAGS) {|type, width, precision, sp, hs, pl, mi, zr|
format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}"
define_method("test_format_float(#{format})", assertions_format_float(format))
}
end end

View file

@ -1,10 +1,10 @@
#define RUBY_VERSION "2.0.0" #define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2013-09-14" #define RUBY_RELEASE_DATE "2013-09-15"
#define RUBY_PATCHLEVEL 313 #define RUBY_PATCHLEVEL 314
#define RUBY_RELEASE_YEAR 2013 #define RUBY_RELEASE_YEAR 2013
#define RUBY_RELEASE_MONTH 9 #define RUBY_RELEASE_MONTH 9
#define RUBY_RELEASE_DAY 14 #define RUBY_RELEASE_DAY 15
#include "ruby/version.h" #include "ruby/version.h"

View file

@ -489,14 +489,19 @@ BSD__ultoa(register u_long val, char *endp, int base, int octzero, const char *x
#ifdef FLOATING_POINT #ifdef FLOATING_POINT
#include <math.h> #include <math.h>
#include <float.h>
/* #include "floatio.h" */ /* #include "floatio.h" */
#ifndef MAXEXP #ifndef MAXEXP
# define MAXEXP 1024 # if DBL_MAX_10_EXP > -DBL_MIN_10_EXP
# define MAXEXP (DBL_MAX_10_EXP)
# else
# define MAXEXP (-DBL_MIN_10_EXP)
# endif
#endif #endif
#ifndef MAXFRACT #ifndef MAXFRACT
# define MAXFRACT 64 # define MAXFRACT (MAXEXP*10/3)
#endif #endif
#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
@ -547,6 +552,7 @@ BSD_vfprintf(FILE *fp, const char *fmt0, va_list ap)
int expt; /* integer value of exponent */ int expt; /* integer value of exponent */
int expsize = 0; /* character count for expstr */ int expsize = 0; /* character count for expstr */
int ndig = 0; /* actual number of digits returned by cvt */ int ndig = 0; /* actual number of digits returned by cvt */
int fprec = 0; /* floating point precision */
char expstr[7]; /* buffer for exponent string */ char expstr[7]; /* buffer for exponent string */
#endif #endif
u_long UNINITIALIZED_VAR(ulval); /* integer arguments %[diouxX] */ u_long UNINITIALIZED_VAR(ulval); /* integer arguments %[diouxX] */
@ -851,6 +857,7 @@ reswitch: switch (ch) {
if (prec > 0) { if (prec > 0) {
flags |= ALT; flags |= ALT;
prec++; prec++;
fprec = prec;
} }
goto fp_begin; goto fp_begin;
case 'e': /* anomalous precision */ case 'e': /* anomalous precision */
@ -858,7 +865,7 @@ reswitch: switch (ch) {
if (prec != 0) if (prec != 0)
flags |= ALT; flags |= ALT;
prec = (prec == -1) ? prec = (prec == -1) ?
DEFPREC + 1 : prec + 1; DEFPREC + 1 : (fprec = prec + 1);
/* FALLTHROUGH */ /* FALLTHROUGH */
goto fp_begin; goto fp_begin;
case 'f': /* always print trailing zeroes */ case 'f': /* always print trailing zeroes */
@ -868,6 +875,8 @@ reswitch: switch (ch) {
case 'G': case 'G':
if (prec == -1) if (prec == -1)
prec = DEFPREC; prec = DEFPREC;
else
fprec = prec;
fp_begin: _double = va_arg(ap, double); fp_begin: _double = va_arg(ap, double);
/* do this before tricky precision changes */ /* do this before tricky precision changes */
if (isinf(_double)) { if (isinf(_double)) {
@ -883,7 +892,7 @@ fp_begin: _double = va_arg(ap, double);
break; break;
} }
flags |= FPT; flags |= FPT;
cp = cvt(_double, prec, flags, &softsign, cp = cvt(_double, (prec < MAXFRACT ? prec : MAXFRACT), flags, &softsign,
&expt, ch, &ndig, buf); &expt, ch, &ndig, buf);
if (ch == 'g' || ch == 'G') { if (ch == 'g' || ch == 'G') {
if (expt <= -4 || (expt > prec && expt > 1)) if (expt <= -4 || (expt > prec && expt > 1))
@ -905,7 +914,7 @@ fp_begin: _double = va_arg(ap, double);
expsize = exponent(expstr, expt, ch); expsize = exponent(expstr, expt, ch);
size = expsize + ndig; size = expsize + ndig;
if (ndig > 1 || flags & ALT) if (ndig > 1 || flags & ALT)
++size; ++fprec, ++size;
} else if (ch == 'f') { /* f fmt */ } else if (ch == 'f') { /* f fmt */
if (expt > 0) { if (expt > 0) {
size = expt; size = expt;
@ -1137,6 +1146,7 @@ long_len:
if (ndig > 0) PRINT(cp, ndig-1); if (ndig > 0) PRINT(cp, ndig-1);
} else /* XpYYY */ } else /* XpYYY */
PRINT(cp, 1); PRINT(cp, 1);
PAD(fprec-ndig, zeroes);
PRINT(expstr, expsize); PRINT(expstr, expsize);
} }
else if (ch >= 'f') { /* 'f' or 'g' */ else if (ch >= 'f') { /* 'f' or 'g' */
@ -1147,7 +1157,8 @@ long_len:
PRINT("0", 1); PRINT("0", 1);
} else { } else {
PRINT("0.", 2); PRINT("0.", 2);
PAD(ndig - 1, zeroes); PAD((ndig >= fprec ? ndig - 1 : fprec - (ch != 'f')),
zeroes);
} }
} else if (expt == 0 && ndig == 0 && (flags & ALT) == 0) { } else if (expt == 0 && ndig == 0 && (flags & ALT) == 0) {
PRINT("0", 1); PRINT("0", 1);
@ -1155,6 +1166,8 @@ long_len:
PRINT("0.", 2); PRINT("0.", 2);
PAD(-expt, zeroes); PAD(-expt, zeroes);
PRINT(cp, ndig); PRINT(cp, ndig);
if (flags & ALT)
PAD(fprec - ndig + (ch == 'f' ? expt : 0), zeroes);
} else if (expt >= ndig) { } else if (expt >= ndig) {
PRINT(cp, ndig); PRINT(cp, ndig);
PAD(expt - ndig, zeroes); PAD(expt - ndig, zeroes);
@ -1165,6 +1178,8 @@ long_len:
cp += expt; cp += expt;
PRINT(".", 1); PRINT(".", 1);
PRINT(cp, ndig-expt); PRINT(cp, ndig-expt);
if (flags & ALT)
PAD(fprec - ndig + (ch == 'f' ? expt : 0), zeroes);
} }
} else { /* 'e' or 'E' */ } else { /* 'e' or 'E' */
if (ndig > 1 || flags & ALT) { if (ndig > 1 || flags & ALT) {
@ -1176,6 +1191,7 @@ long_len:
} else /* 0.[0..] */ } else /* 0.[0..] */
/* __dtoa irregularity */ /* __dtoa irregularity */
PAD(ndig - 1, zeroes); PAD(ndig - 1, zeroes);
if (flags & ALT) PAD(fprec - ndig - 1, zeroes);
} else /* XeYYY */ } else /* XeYYY */
PRINT(cp, 1); PRINT(cp, 1);
PRINT(expstr, expsize); PRINT(expstr, expsize);
@ -1255,7 +1271,7 @@ static int
exponent(char *p0, int exp, int fmtch) exponent(char *p0, int exp, int fmtch)
{ {
register char *p, *t; register char *p, *t;
char expbuf[MAXEXP]; char expbuf[2 + (MAXEXP < 1000 ? 3 : MAXEXP < 10000 ? 4 : 5)]; /* >= 2 + ceil(log10(MAXEXP)) */
p = p0; p = p0;
*p++ = fmtch; *p++ = fmtch;
@ -1265,13 +1281,13 @@ exponent(char *p0, int exp, int fmtch)
} }
else else
*p++ = '+'; *p++ = '+';
t = expbuf + MAXEXP; t = expbuf + sizeof(expbuf);
if (exp > 9) { if (exp > 9) {
do { do {
*--t = to_char(exp % 10); *--t = to_char(exp % 10);
} while ((exp /= 10) > 9); } while ((exp /= 10) > 9);
*--t = to_char(exp); *--t = to_char(exp);
for (; t < expbuf + MAXEXP; *p++ = *t++); for (; t < expbuf + sizeof(expbuf); *p++ = *t++);
} }
else { else {
if (fmtch & 15) *p++ = '0'; /* other than p or P */ if (fmtch & 15) *p++ = '0'; /* other than p or P */