mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* sprintf.c (rb_f_sprintf): more checks for format argument.
[ruby-core:11569], [ruby-core:11570], [ruby-core:11571], [ruby-core:11573] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12803 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
66e1be60c3
commit
192c936e23
3 changed files with 74 additions and 26 deletions
|
@ -1,3 +1,9 @@
|
|||
Mon Jul 16 05:45:53 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* sprintf.c (rb_f_sprintf): more checks for format argument.
|
||||
[ruby-core:11569], [ruby-core:11570], [ruby-core:11571],
|
||||
[ruby-core:11573]
|
||||
|
||||
Mon Jul 16 00:26:10 2007 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* bignum.c (rb_big_pow): removed invariant variable. [ruby-dev:31236]
|
||||
|
|
61
sprintf.c
61
sprintf.c
|
@ -79,6 +79,7 @@ sign_bits(int base, const char *p)
|
|||
#define FSPACE 16
|
||||
#define FWIDTH 32
|
||||
#define FPREC 64
|
||||
#define FPREC0 128
|
||||
|
||||
#define CHECK(l) do {\
|
||||
while (blen + (l) >= bsiz) {\
|
||||
|
@ -113,9 +114,7 @@ sign_bits(int base, const char *p)
|
|||
#define GETNTHARG(nth) \
|
||||
((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[nth])
|
||||
|
||||
#define GETASTER(val) do { \
|
||||
t = p++; \
|
||||
n = 0; \
|
||||
#define GETNUM(n, val) \
|
||||
for (; p < end && ISDIGIT(*p); p++) { \
|
||||
int next_n = 10 * n + (*p - '0'); \
|
||||
if (next_n / 10 != n) {\
|
||||
|
@ -125,7 +124,12 @@ sign_bits(int base, const char *p)
|
|||
} \
|
||||
if (p >= end) { \
|
||||
rb_raise(rb_eArgError, "malformed format string - %%*[0-9]"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GETASTER(val) do { \
|
||||
t = p++; \
|
||||
n = 0; \
|
||||
GETNUM(n, val); \
|
||||
if (*p == '$') { \
|
||||
tmp = GETPOSARG(n); \
|
||||
} \
|
||||
|
@ -263,6 +267,21 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
|||
VALUE tmp;
|
||||
VALUE str;
|
||||
|
||||
#define CHECK_FOR_WIDTH(f) \
|
||||
if ((f) & FWIDTH) { \
|
||||
rb_raise(rb_eArgError, "width given twice"); \
|
||||
} \
|
||||
if ((f) & FPREC0) { \
|
||||
rb_raise(rb_eArgError, "width after precision"); \
|
||||
}
|
||||
#define CHECK_FOR_FLAGS(f) \
|
||||
if ((f) & FWIDTH) { \
|
||||
rb_raise(rb_eArgError, "flag after width"); \
|
||||
} \
|
||||
if ((f) & FPREC0) { \
|
||||
rb_raise(rb_eArgError, "flag after precision"); \
|
||||
}
|
||||
|
||||
++argc;
|
||||
--argv;
|
||||
if (OBJ_TAINTED(fmt)) tainted = 1;
|
||||
|
@ -299,43 +318,40 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
|||
break;
|
||||
|
||||
case ' ':
|
||||
CHECK_FOR_FLAGS(flags);
|
||||
flags |= FSPACE;
|
||||
p++;
|
||||
goto retry;
|
||||
|
||||
case '#':
|
||||
CHECK_FOR_FLAGS(flags);
|
||||
flags |= FSHARP;
|
||||
p++;
|
||||
goto retry;
|
||||
|
||||
case '+':
|
||||
CHECK_FOR_FLAGS(flags);
|
||||
flags |= FPLUS;
|
||||
p++;
|
||||
goto retry;
|
||||
|
||||
case '-':
|
||||
CHECK_FOR_FLAGS(flags);
|
||||
flags |= FMINUS;
|
||||
p++;
|
||||
goto retry;
|
||||
|
||||
case '0':
|
||||
CHECK_FOR_FLAGS(flags);
|
||||
flags |= FZERO;
|
||||
p++;
|
||||
goto retry;
|
||||
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
CHECK_FOR_WIDTH(flags);
|
||||
n = 0;
|
||||
for (; p < end && ISDIGIT(*p); p++) {
|
||||
int next_n = 10 * n + (*p - '0');
|
||||
if (next_n / 10 != n) {
|
||||
rb_raise(rb_eArgError, "width too big");
|
||||
}
|
||||
n = next_n;
|
||||
}
|
||||
if (p >= end) {
|
||||
rb_raise(rb_eArgError, "malformed format string - %%[0-9]");
|
||||
}
|
||||
GETNUM(n, width);
|
||||
if (*p == '$') {
|
||||
if (nextvalue != Qundef) {
|
||||
rb_raise(rb_eArgError, "value given twice - %d$", n);
|
||||
|
@ -349,9 +365,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
|||
goto retry;
|
||||
|
||||
case '*':
|
||||
if (flags & FWIDTH) {
|
||||
rb_raise(rb_eArgError, "width given twice");
|
||||
}
|
||||
CHECK_FOR_WIDTH(flags);
|
||||
flags |= FWIDTH;
|
||||
GETASTER(width);
|
||||
if (width < 0) {
|
||||
|
@ -362,10 +376,10 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
|||
goto retry;
|
||||
|
||||
case '.':
|
||||
if (flags & FPREC) {
|
||||
if (flags & FPREC0) {
|
||||
rb_raise(rb_eArgError, "precision given twice");
|
||||
}
|
||||
flags |= FPREC;
|
||||
flags |= FPREC|FPREC0;
|
||||
|
||||
prec = 0;
|
||||
p++;
|
||||
|
@ -378,17 +392,12 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
|
|||
goto retry;
|
||||
}
|
||||
|
||||
for (; p < end && ISDIGIT(*p); p++) {
|
||||
prec = 10 * prec + (*p - '0');
|
||||
}
|
||||
if (p >= end) {
|
||||
rb_raise(rb_eArgError, "malformed format string - %%.[0-9]");
|
||||
}
|
||||
GETNUM(prec, precision);
|
||||
goto retry;
|
||||
|
||||
case '\n':
|
||||
p--;
|
||||
case '\0':
|
||||
p--;
|
||||
case '%':
|
||||
if (flags != FNONE) {
|
||||
rb_raise(rb_eArgError, "illegal format character - %%");
|
||||
|
|
|
@ -138,4 +138,37 @@ class TestSprintf < Test::Unit::TestCase
|
|||
assert_equal("-Inf ", sprintf("%- 08f", -inf))
|
||||
assert_equal("-0000Inf", sprintf("%+ 08f", -inf))
|
||||
end
|
||||
|
||||
def test_invalid
|
||||
# [ruby-core:11569]
|
||||
|
||||
# Star precision before star width:
|
||||
assert_raise(ArgumentError) {sprintf("%.**d", 5, 10, 1)}
|
||||
|
||||
# Precision before flags and width:
|
||||
assert_raise(ArgumentError) {sprintf("%.5+05d", 5)}
|
||||
assert_raise(ArgumentError) {sprintf("%.5 5d", 5)}
|
||||
|
||||
# Overriding a star width with a numeric one:
|
||||
assert_raise(ArgumentError) {sprintf("%*1s", 5, 1)}
|
||||
|
||||
# Width before flags:
|
||||
assert_raise(ArgumentError) {sprintf("%5+0d", 1)}
|
||||
assert_raise(ArgumentError) {sprintf("%5 0d", 1)}
|
||||
|
||||
# Specifying width multiple times:
|
||||
assert_raise(ArgumentError) {sprintf("%50+30+20+10+5d", 5)}
|
||||
assert_raise(ArgumentError) {sprintf("%50 30 20 10 5d", 5)}
|
||||
|
||||
# [ruby-core:11570]
|
||||
# Specifying the precision multiple times with negative star arguments:
|
||||
assert_raise(ArgumentError) {sprintf("%.*.*.*.*f", -1, -1, -1, 5, 1)}
|
||||
|
||||
# [ruby-core:11571]
|
||||
# Null bytes after percent signs are removed:
|
||||
assert_equal("%\0x hello", sprintf("%\0x hello"))
|
||||
|
||||
# [ruby-core:11573]
|
||||
assert_raise(ArgumentError) {sprintf("%.25555555555555555555555555555555555555s", "hello")}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue