sprintf.c: refactor Rational f

* sprintf.c (rb_str_format): refactor floating point format of
  Rational by using gereric Integer functions.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54306 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2016-03-27 23:19:50 +00:00
parent 21102e16ac
commit 7d378a5b3a
2 changed files with 27 additions and 26 deletions

View File

@ -1,4 +1,7 @@
Mon Mar 28 08:18:51 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> Mon Mar 28 08:19:49 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
* sprintf.c (rb_str_format): refactor floating point format of
Rational by using gereric Integer functions.
* sprintf.c (rb_str_format): fix buffer overflow, length must be * sprintf.c (rb_str_format): fix buffer overflow, length must be
greater than precision. reported by William Bowling <will AT greater than precision. reported by William Bowling <will AT

View File

@ -65,12 +65,20 @@ sign_bits(int base, const char *p)
#define PUSH(s, l) do { \ #define PUSH(s, l) do { \
CHECK(l);\ CHECK(l);\
PUSH_(s, l);\
} while (0)
#define PUSH_(s, l) do { \
memcpy(&buf[blen], (s), (l));\ memcpy(&buf[blen], (s), (l));\
blen += (l);\ blen += (l);\
} while (0) } while (0)
#define FILL(c, l) do { \ #define FILL(c, l) do { \
CHECK(l);\ CHECK(l);\
FILL_(c, l);\
} while (0)
#define FILL_(c, l) do { \
memset(&buf[blen], (c), (l));\ memset(&buf[blen], (c), (l));\
blen += (l);\ blen += (l);\
} while (0) } while (0)
@ -1034,8 +1042,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
{ {
VALUE val = GETARG(), num, den; VALUE val = GETARG(), num, den;
int sign = (flags&FPLUS) ? 1 : 0, zero = 0; int sign = (flags&FPLUS) ? 1 : 0, zero = 0;
long len, done = blen; long len, fill;
int prefix = 0;
if (FIXNUM_P(val) || RB_TYPE_P(val, T_BIGNUM)) { if (FIXNUM_P(val) || RB_TYPE_P(val, T_BIGNUM)) {
den = INT2FIX(1); den = INT2FIX(1);
num = val; num = val;
@ -1074,15 +1081,20 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
if (sign || (flags&FSPACE)) ++len; if (sign || (flags&FSPACE)) ++len;
if (prec > 0) ++len; /* period */ if (prec > 0) ++len; /* period */
CHECK(len > width ? len : width); CHECK(len > width ? len : width);
fill = width > len ? width - len : 0;
if (fill && !(flags&FMINUS) && !(flags&FZERO)) {
FILL_(' ', fill);
}
if (sign || (flags&FSPACE)) { if (sign || (flags&FSPACE)) {
buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' '; buf[blen++] = sign > 0 ? '+' : sign < 0 ? '-' : ' ';
prefix++; }
if (fill && !(flags&FMINUS) && (flags&FZERO)) {
FILL_('0', fill);
} }
len = RSTRING_LEN(val) + zero; len = RSTRING_LEN(val) + zero;
t = RSTRING_PTR(val); t = RSTRING_PTR(val);
if (len > prec) { if (len > prec) {
memcpy(&buf[blen], t, len - prec); PUSH_(t, len - prec);
blen += len - prec;
} }
else { else {
buf[blen++] = '0'; buf[blen++] = '0';
@ -1091,31 +1103,17 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
buf[blen++] = '.'; buf[blen++] = '.';
} }
if (zero) { if (zero) {
FILL('0', zero); FILL_('0', zero);
} }
else if (prec > len) { else if (prec > len) {
FILL('0', prec - len); FILL_('0', prec - len);
memcpy(&buf[blen], t, len); PUSH_(t, len);
blen += len;
} }
else if (prec > 0) { else if (prec > 0) {
memcpy(&buf[blen], t + len - prec, prec); PUSH_(t + len - prec, prec);
blen += prec;
} }
if ((flags & FWIDTH) && width > (done = blen - done)) { if (fill && (flags&FMINUS)) {
int fill = ' '; FILL_(' ', fill);
long shifting = 0;
if (!(flags&FMINUS)) {
shifting = done;
if (flags&FZERO) {
shifting -= prefix;
fill = '0';
}
blen -= shifting;
memmove(&buf[blen + width - done], &buf[blen], shifting);
}
FILL(fill, width - done);
blen += shifting;
} }
RB_GC_GUARD(val); RB_GC_GUARD(val);
break; break;