diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-09-19 07:25:09 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-09-19 07:25:09 +0000 |
commit | 170344b20ec9e3340d9bb41e9f7434ccd2ae6365 (patch) | |
tree | 38d111015f600d013efb72d035108ebe33e8c518 | |
parent | 3145683203c5673da67676fecb4b7efdfec72653 (diff) |
vsnprintf.c: initialize cp
* vsnprintf.c (BSD_vfprintf): initialize cp so that size is 0 in the
commented case. fix an accidental bug at r16716.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42977 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | ext/-test-/printf/printf.c | 62 | ||||
-rw-r--r-- | test/-ext-/test_printf.rb | 138 | ||||
-rw-r--r-- | vsnprintf.c | 1 |
4 files changed, 206 insertions, 0 deletions
@@ -1,3 +1,8 @@ +Thu Sep 19 16:25:06 2013 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * vsnprintf.c (BSD_vfprintf): initialize cp so that size is 0 in the + commented case. fix an accidental bug at r16716. + Thu Sep 19 14:33:14 2013 Koichi Sasada <ko1@atdot.net> * NEWS: add a news for r42974. diff --git a/ext/-test-/printf/printf.c b/ext/-test-/printf/printf.c index 28a158beb4..53aad85f19 100644 --- a/ext/-test-/printf/printf.c +++ b/ext/-test-/printf/printf.c @@ -27,6 +27,67 @@ printf_test_q(VALUE self, VALUE obj) return rb_enc_sprintf(rb_usascii_encoding(), "[% "PRIsVALUE"]", obj); } +static char * +utoa(char *p, char *e, unsigned int x) +{ + char *e0 = e; + if (e <= p) return p; + do { + *--e = x % 10 + '0'; + } while ((x /= 10) != 0 && e > p); + memmove(p, e, e0 - e); + return p + (e0 - e); +} + +static VALUE +printf_test_call(int argc, VALUE *argv, VALUE self) +{ + VALUE opt, type, num; + char format[sizeof(int) * 6 + 8], *p = format, cnv; + int n; + + rb_scan_args(argc, argv, "2:", &type, &num, &opt); + Check_Type(type, T_STRING); + if (RSTRING_LEN(type) != 1) rb_raise(rb_eArgError, "wrong length(%ld)", RSTRING_LEN(type)); + switch (cnv = RSTRING_PTR(type)[0]) { + case 'd': case 'x': case 'o': case 'X': break; + default: rb_raise(rb_eArgError, "wrong conversion(%c)", cnv); + } + n = NUM2INT(num); + *p++ = '%'; + if (!NIL_P(opt)) { + VALUE v; + Check_Type(opt, T_HASH); + if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("space"))))) { + *p++ = ' '; + } + if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("hash"))))) { + *p++ = '#'; + } + if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("plus"))))) { + *p++ = '+'; + } + if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("minus"))))) { + *p++ = '-'; + } + if (RTEST(rb_hash_aref(opt, ID2SYM(rb_intern("zero"))))) { + *p++ = '0'; + } + if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("width"))))) { + p = utoa(p, format + sizeof(format), NUM2UINT(v)); + } + if (!NIL_P(v = rb_hash_aref(opt, ID2SYM(rb_intern("prec"))))) { + *p++ = '.'; + if (FIXNUM_P(v)) + p = utoa(p, p + sizeof(format), NUM2UINT(v)); + } + } + *p++ = cnv; + *p++ = '\0'; + return rb_assoc_new(rb_enc_sprintf(rb_usascii_encoding(), format, n), + rb_usascii_str_new_cstr(format)); +} + void Init_printf(void) { @@ -35,4 +96,5 @@ Init_printf(void) rb_define_singleton_method(m, "s", printf_test_s, 1); rb_define_singleton_method(m, "v", printf_test_v, 1); rb_define_singleton_method(m, "q", printf_test_q, 1); + rb_define_singleton_method(m, "call", printf_test_call, -1); } diff --git a/test/-ext-/test_printf.rb b/test/-ext-/test_printf.rb index 4532c371b4..609af7ca7a 100644 --- a/test/-ext-/test_printf.rb +++ b/test/-ext-/test_printf.rb @@ -1,5 +1,6 @@ require 'test/unit' require "-test-/printf" +require_relative '../ruby/allpairs' class Test_SPrintf < Test::Unit::TestCase def to_s @@ -43,4 +44,141 @@ class Test_SPrintf < Test::Unit::TestCase inspect: Bug::Printf.v(obj).tainted?, }) end + + VS = [ + #-0x1000000000000000000000000000000000000000000000002, + #-0x1000000000000000000000000000000000000000000000001, + #-0x1000000000000000000000000000000000000000000000000, + #-0xffffffffffffffffffffffffffffffffffffffffffffffff, + #-0x1000000000000000000000002, + #-0x1000000000000000000000001, + #-0x1000000000000000000000000, + #-0xffffffffffffffffffffffff, + -0x10000000000000002, + -0x10000000000000001, + -0x10000000000000000, + -0xffffffffffffffff, + -0x4000000000000002, + -0x4000000000000001, + -0x4000000000000000, + -0x3fffffffffffffff, + -0x100000002, + -0x100000001, + -0x100000000, + -0xffffffff, + #-0xc717a08d, # 0xc717a08d * 0x524b2245 = 0x4000000000000001 + -0x80000002, + -0x80000001, + -0x80000000, + -0x7fffffff, + #-0x524b2245, + -0x40000002, + -0x40000001, + -0x40000000, + -0x3fffffff, + #-0x10002, + #-0x10001, + #-0x10000, + #-0xffff, + #-0x8101, # 0x8101 * 0x7f01 = 0x40000001 + #-0x8002, + #-0x8001, + #-0x8000, + #-0x7fff, + #-0x7f01, + #-65, + #-64, + #-63, + #-62, + #-33, + #-32, + #-31, + #-30, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + #30, + #31, + #32, + #33, + #62, + #63, + #64, + #65, + #0x7f01, + #0x7ffe, + #0x7fff, + #0x8000, + #0x8001, + #0x8101, + #0xfffe, + #0xffff, + #0x10000, + #0x10001, + 0x3ffffffe, + 0x3fffffff, + 0x40000000, + 0x40000001, + #0x524b2245, + 0x7ffffffe, + 0x7fffffff, + 0x80000000, + 0x80000001, + #0xc717a08d, + 0xfffffffe, + 0xffffffff, + 0x100000000, + 0x100000001, + 0x3ffffffffffffffe, + 0x3fffffffffffffff, + 0x4000000000000000, + 0x4000000000000001, + 0xfffffffffffffffe, + 0xffffffffffffffff, + 0x10000000000000000, + 0x10000000000000001, + #0xffffffffffffffffffffffff, + #0x1000000000000000000000000, + #0x1000000000000000000000001, + #0xffffffffffffffffffffffffffffffffffffffffffffffff, + #0x1000000000000000000000000000000000000000000000000, + #0x1000000000000000000000000000000000000000000000001 + ] + VS.reverse! + + FLAGS = [[nil, ' '], [nil, '#'], [nil, '+'], [nil, '-'], [nil, '0']] + + def self.assertions_format_integer(format, type, **opts) + proc { + VS.each {|v| + begin + r = Bug::Printf.(type, v, **opts) + rescue RangeError + else + e = sprintf format, v + assert_equal([e, format], r, "rb_sprintf(#{format.dump}, #{v})") + end + } + } + end + + AllPairs.each(%w[d], + # octal and hexadecimal deal with negative values differently + [nil, 0, 5, 20], + [nil, true, 0], # 8, 20 + *FLAGS) { + |type, width, prec, sp, hs, pl, mi, zr| + precision = ".#{prec unless prec == true}" if prec + format = "%#{sp}#{hs}#{pl}#{mi}#{zr}#{width}#{precision}#{type}" + define_method("test_format_integer(#{format})", + assertions_format_integer(format, type, + space: sp, hash: hs, + plus: pl, minus: mi, + zero: zr, width: width, + prec: prec)) + } end diff --git a/vsnprintf.c b/vsnprintf.c index 9778f039c5..8958aaa41f 100644 --- a/vsnprintf.c +++ b/vsnprintf.c @@ -1060,6 +1060,7 @@ number: if ((dprec = prec) >= 0) * explicit precision of zero is no characters.'' * -- ANSI X3J11 */ + cp = ebuf; #ifdef _HAVE_SANE_QUAD_ if (flags & QUADINT) { if (uqval != 0 || prec != 0) |