summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-10-31 14:36:35 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-10-31 14:36:35 +0000
commitc75767b4b0c7444181add617d6005c133a15a8c6 (patch)
tree3e3062a8414aee438ed3625ec121ce8d566df53e
parent739c6cea04909055e19e9e86c7487d495136e4cf (diff)
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_1_9_3@43488 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog10
-rw-r--r--test/ruby/test_sprintf_comb.rb46
-rw-r--r--version.h2
-rw-r--r--vsnprintf.c34
4 files changed, 59 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 0de7de1373..c99a4aeeed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Thu Oct 31 23:35:12 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.
+
Thu Oct 31 23:32:41 2013 Michal Rokos <michal@rokos.cz>
* configure.in (sys/pstat.h): fix missing header check for
diff --git a/test/ruby/test_sprintf_comb.rb b/test/ruby/test_sprintf_comb.rb
index 261732bcbc..c58ddf4f15 100644
--- a/test/ruby/test_sprintf_comb.rb
+++ b/test/ruby/test_sprintf_comb.rb
@@ -107,7 +107,9 @@ class TestSprintfComb < Test::Unit::TestCase
]
VS.reverse!
- def combination(*args, &b)
+ FLAGS = [['', ' '], ['', '#'], ['', '+'], ['', '-'], ['', '0']]
+
+ def self.combination(*args, &b)
#AllPairs.exhaustive_each(*args, &b)
AllPairs.each(*args, &b)
end
@@ -268,17 +270,8 @@ class TestSprintfComb < Test::Unit::TestCase
str
end
- def test_format_integer
- combination(
- %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}"
+ def self.assertions_format_integer(format)
+ proc {
VS.each {|v|
r = sprintf format, v
e = emu_int format, v
@@ -293,6 +286,14 @@ class TestSprintfComb < Test::Unit::TestCase
}
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 = [
-1e100,
-123456789.0,
@@ -526,17 +527,8 @@ class TestSprintfComb < Test::Unit::TestCase
end
- def test_format_float
- combination(
- %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}"
+ def self.assertions_format_float(format)
+ proc {
FLOAT_VALUES.each {|v|
r = sprintf format, v
e = emu_float format, v
@@ -550,4 +542,12 @@ class TestSprintfComb < Test::Unit::TestCase
}
}
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
diff --git a/version.h b/version.h
index 448e9fc286..f27435bb01 100644
--- a/version.h
+++ b/version.h
@@ -1,5 +1,5 @@
#define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 476
+#define RUBY_PATCHLEVEL 477
#define RUBY_RELEASE_DATE "2013-10-31"
#define RUBY_RELEASE_YEAR 2013
diff --git a/vsnprintf.c b/vsnprintf.c
index 79bde9f485..214b2c639a 100644
--- a/vsnprintf.c
+++ b/vsnprintf.c
@@ -489,14 +489,19 @@ BSD__ultoa(register u_long val, char *endp, int base, int octzero, const char *x
#ifdef FLOATING_POINT
#include <math.h>
+#include <float.h>
/* #include "floatio.h" */
#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
#ifndef MAXFRACT
-# define MAXFRACT 64
+# define MAXFRACT (MAXEXP*10/3)
#endif
#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 expsize = 0; /* character count for expstr */
int ndig = 0; /* actual number of digits returned by cvt */
+ int fprec = 0; /* floating point precision */
char expstr[7]; /* buffer for exponent string */
#endif
u_long UNINITIALIZED_VAR(ulval); /* integer arguments %[diouxX] */
@@ -813,6 +819,7 @@ reswitch: switch (ch) {
if (prec > 0) {
flags |= ALT;
prec++;
+ fprec = prec;
}
goto fp_begin;
case 'e': /* anomalous precision */
@@ -820,7 +827,7 @@ reswitch: switch (ch) {
if (prec != 0)
flags |= ALT;
prec = (prec == -1) ?
- DEFPREC + 1 : prec + 1;
+ DEFPREC + 1 : (fprec = prec + 1);
/* FALLTHROUGH */
goto fp_begin;
case 'f': /* always print trailing zeroes */
@@ -830,6 +837,8 @@ reswitch: switch (ch) {
case 'G':
if (prec == -1)
prec = DEFPREC;
+ else
+ fprec = prec;
fp_begin: _double = va_arg(ap, double);
/* do this before tricky precision changes */
if (isinf(_double)) {
@@ -845,7 +854,7 @@ fp_begin: _double = va_arg(ap, double);
break;
}
flags |= FPT;
- cp = cvt(_double, prec, flags, &softsign,
+ cp = cvt(_double, (prec < MAXFRACT ? prec : MAXFRACT), flags, &softsign,
&expt, ch, &ndig, buf);
if (ch == 'g' || ch == 'G') {
if (expt <= -4 || (expt > prec && expt > 1))
@@ -867,7 +876,7 @@ fp_begin: _double = va_arg(ap, double);
expsize = exponent(expstr, expt, ch);
size = expsize + ndig;
if (ndig > 1 || flags & ALT)
- ++size;
+ ++fprec, ++size;
} else if (ch == 'f') { /* f fmt */
if (expt > 0) {
size = expt;
@@ -1099,6 +1108,7 @@ long_len:
if (ndig > 0) PRINT(cp, ndig-1);
} else /* XpYYY */
PRINT(cp, 1);
+ PAD(fprec-ndig, zeroes);
PRINT(expstr, expsize);
}
else if (ch >= 'f') { /* 'f' or 'g' */
@@ -1109,7 +1119,8 @@ long_len:
PRINT("0", 1);
} else {
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) {
PRINT("0", 1);
@@ -1117,6 +1128,8 @@ long_len:
PRINT("0.", 2);
PAD(-expt, zeroes);
PRINT(cp, ndig);
+ if (flags & ALT)
+ PAD(fprec - ndig + (ch == 'f' ? expt : 0), zeroes);
} else if (expt >= ndig) {
PRINT(cp, ndig);
PAD(expt - ndig, zeroes);
@@ -1127,6 +1140,8 @@ long_len:
cp += expt;
PRINT(".", 1);
PRINT(cp, ndig-expt);
+ if (flags & ALT)
+ PAD(fprec - ndig + (ch == 'f' ? expt : 0), zeroes);
}
} else { /* 'e' or 'E' */
if (ndig > 1 || flags & ALT) {
@@ -1138,6 +1153,7 @@ long_len:
} else /* 0.[0..] */
/* __dtoa irregularity */
PAD(ndig - 1, zeroes);
+ if (flags & ALT) PAD(fprec - ndig - 1, zeroes);
} else /* XeYYY */
PRINT(cp, 1);
PRINT(expstr, expsize);
@@ -1222,7 +1238,7 @@ exponent(p0, exp, fmtch)
int exp, fmtch;
{
register char *p, *t;
- char expbuf[MAXEXP];
+ char expbuf[2 + (MAXEXP < 1000 ? 3 : MAXEXP < 10000 ? 4 : 5)]; /* >= 2 + ceil(log10(MAXEXP)) */
p = p0;
*p++ = fmtch;
@@ -1232,13 +1248,13 @@ exponent(p0, exp, fmtch)
}
else
*p++ = '+';
- t = expbuf + MAXEXP;
+ t = expbuf + sizeof(expbuf);
if (exp > 9) {
do {
*--t = to_char(exp % 10);
} while ((exp /= 10) > 9);
*--t = to_char(exp);
- for (; t < expbuf + MAXEXP; *p++ = *t++);
+ for (; t < expbuf + sizeof(expbuf); *p++ = *t++);
}
else {
if (fmtch & 15) *p++ = '0'; /* other than p or P */