Negative allocation size in rb_f_sprintf

Tietew e$B$G$9!#e(B

Railse$B$rF0$+$7$F$$$k$HI=Bj$N%(%i!<$,=P$F:$$C$F$$$^$9!#e(B
e$B4D6-$Oe(B
e$B!&e(BDebian sid (Linux 2.6.20, x86_64)
e$B!&e(Bglibc 2.6.1-1
e$B!&e(Bgcc 4.1.3 20070718 (prerelease) (Debian 4.1.2-14)
e$B!&e(BRuby 1.8 (SVN HEAD)
e$B$G$9!#e(B

gdbe$B$GDI$$$J$,$i$3$N%a!<%k=q$$$F$^$9!#e(B

e$B$I$3$+$Ge(B len=-1 e$B$Je(B Bignum e$B$,@8@.$5$l$F$$$k$C$]$$$G$9!#e(B
gdbe$B$GC0G0$KDI$C$?$H$3$m!“e(B”%d" e$B$Ke(B 1 e$BL$K~$Ne(B Float
e$B$rM?$($k$H:F8=$7e(B
e$B$^$7$?!#860x$Oe(B rb_dbl2big e$B$+!)e(B

tietew@tomoyo:~$ ruby -ve ‘p “%d” % 0.9’
ruby 1.8.6 (2007-08-07 patchlevel 5000) [x86_64-linux]
-e:1:in `%’: negative allocation size (or too big) (NoMemoryError)

e$B$A$J$_$Ke(B i686 e$B$@$H:F8=$7$^$;$s!#e(B

tietew@argon:~/ruby/ruby_1_8$ ruby -ve ‘printf “%d\n”, 0.9’
ruby 1.8.6 (2007-08-07 patchlevel 5000) [i686-linux]
0

e$BDI$C$?2aDx$G$9e(B

** Rubye$B%P%C%/%H%l!<%9e(B
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/benchmarking.rb:78:in
sprintf' /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/benchmarking.rb:78:inrendering_runtime’
/usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.1/lib/action_controller/benchmarking.rb:68:in
`perform_action_without_rescue’
… snip …
/usr/local/bin/mongrel_rails:16

** gdbe$B%P%C%/%H%l!<%9e(B
#0 rb_raise (exc=46939774505360,
fmt=0x2ab103c91a80 “negative allocation size (or too big) (required
%ld bytes)”) at error.c:1058
#1 0x00002ab103c0ddf3 in ruby_xmalloc (size=-4) at gc.c:97
#2 0x00002ab103bd76f5 in bignew_1 (klass=46939774491280, len=-1,
sign=1)
at bignum.c:52
#3 0x00002ab103bd7743 in rb_big_clone (x=46939851488600) at bignum.c:63
#4 0x00002ab103bd8d2e in rb_big2str0 (x=46939851488600, base=10,
trim=2)
at bignum.c:691
#5 0x00002ab103bd8f89 in rb_big2str (x=46939851488600, base=10)
at bignum.c:733
#6 0x00002ab103c76e4d in rb_f_sprintf (argc=2, argv=0x7fffa70f46a0)
at sprintf.c:602
… snip …

(gdb) f 3
#3 0x00002ab103bd7743 in rb_big_clone (x=46939851488600) at bignum.c:63
63 VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len,
RBIGNUM(x)->sign);
(gdb) l
58
59 VALUE
60 rb_big_clone(x)
61 VALUE x;
62 {
63 VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len,
RBIGNUM(x)->sign);
64
65 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len);
66 return z;
67 }
(gdb) p (unsigned long)((unsigned char*)x)
$6 = 13
(gdb) p (unsigned long)((unsigned char*)x + 8)
$7 = 46939774491280
(gdb) p (unsigned char)((unsigned char*)x + 16)
$8 = 1 ‘\001’
(gdb) p (long)((unsigned char*)x + 24)
$9 = -1
(gdb) p ((unsigned char*)x + 32)
$10 = (unsigned char *) 0x2ab1092c7d78 “\020?Z\001”
(gdb) p rb_cBignum
$11 = 46939774491280

len=-1 e$B$K$J$C$F$$$ke(B

(gdb) f 6
#6 0x00002ab103c76e4d in rb_f_sprintf (argc=2, argv=0x7fffa70f46a0)
at sprintf.c:602
602 tmp = rb_big2str(val, base);
(gdb) l
597 s = nbuf;
598 goto format_integer;
599 }
600
601 if (sign) {
602 tmp = rb_big2str(val, base);
603 s = RSTRING(tmp)->ptr;
604 if (s[0] == ‘-’) {
605 s++;
606 sc = ‘-’;
(gdb) p val
$12 = 46939851488600
(gdb) p argv[0]
$14 = 46939851488760
(gdb) p argv[1]
$15 = 46939851488680

argv[1] != val

(gdb) p (unsigned long)((unsigned char*)argv[1] + 8)
$35 = 46939774494160
(gdb) p rb_cFloat
$38 = 46939774494160

Float

(gdb) p (double)((unsigned char*)argv[1] + 16)
$39 = 0.71855513799222548

On Tue, 14 Aug 2007 11:29:56 +0900
In article [email protected]
[[ruby-dev:31404] negative allocation size in rb_f_sprintf]
Tietew [email protected] wrote:

e$B$I$3$+$Ge(B len=-1 e$B$Je(B Bignum e$B$,@8@.$5$l$F$$$k$C$]$$$G$9!#e(B
gdbe$B$GC0G0$KDI$C$?$H$3$m!“e(B”%d" e$B$Ke(B 1 e$BL$K~$Ne(B Float e$B$rM?$($k$H:F8=$7e(B
e$B$^$7$?!#860x$Oe(B rb_dbl2big e$B$+!)e(B

tietew@tomoyo:~$ ruby -ve ‘p “%d” % 0.9’
ruby 1.8.6 (2007-08-07 patchlevel 5000) [x86_64-linux]
-e:1:in `%': negative allocation size (or too big) (NoMemoryError)

e$B$H$j$“$($:2<$N%Q%C%A$GD>$j$^$7$?!#e(B
e$B$h$jNI$$=$@5$,$”$j$^$7$?$iC/$+$h$m$7$/$*4j$$$7$^$9!#e(B

Index: bignum.c

— bignum.c (e$B%j%S%8%g%se(B 12928)
+++ bignum.c (e$B:n6H%3%T!<e(B)
@@ -885,6 +885,9 @@
if (isnan(d)) {
rb_raise(rb_eFloatDomainError, “NaN”);
}

  • if ((long)u == 0) {

  • return INT2FIX(0);

  • }

    while (!POSFIXABLE(u) || 0 != (long)u) {
    u /= (double)(BIGRAD);

On Tue, 14 Aug 2007 12:49:52 +0900
In article [email protected]
[[ruby-dev:31406] Re: negative allocation size in rb_f_sprintf]
Tietew [email protected] wrote:

e$B$I$3$+$Ge(B len=-1 e$B$Je(B Bignum e$B$,@8@.$5$l$F$$$k$C$]$$$G$9!#e(B
gdbe$B$GC0G0$KDI$C$?$H$3$m!“e(B”%d" e$B$Ke(B 1 e$BL$K~$Ne(B Float e$B$rM?$($k$H:F8=$7e(B
e$B$^$7$?!#860x$Oe(B rb_dbl2big e$B$+!)e(B

Ruby 1.9 (trunk) e$B$G$b:F8=$7$^$7$?!#e(B

tietew@tomoyo:~/ruby/trunk$ ruby-1.9 -ve ‘“%d” % 0.7’
ruby 1.9.0 (2007-08-15 patchlevel 0) [x86_64-linux]
-e:1: warning: useless use of % in void context
-e:1:in %': negative string size (or size too big) (ArgumentError) from -e:1:in

e$BN.$l$H$7$F$Oe(B

  • dbl2big() e$B$,e(B len=0 e$B$Ne(B Bignum e$B$r@8@.$9$ke(B
  • bigtrunc() e$B$,e(B digits[-2] e$B$^$G8+$K9T$C$F$7$^$&e(B
  • e$B$=$N7k2Le(B len=-1 e$B$K$J$ke(B
  • len=-1 e$B$N$^$^e(B clone e$B$7$h$&$H$7$Fe(B negative allocation
    size

i686e$B$G$O2?8N$+:F8=$7$J$$$N$G$9$,!"e(Bbigtrunc() e$B$,e(B digits[-1]
e$B$rFIe(B
e$B$s$G$7$^$&$N$GF0$/$N$O6vA3$J$N$+$J!#e(B

e$B%Q%C%A$O9THV9f$:$l$F$^$9$,$=$N$^$^Ev$?$k$_$?$$$G$9!#e(B

On Tue, 14 Aug 2007 12:02:09 +0900
In article [email protected]
[[ruby-dev:31405] Re: negative allocation size in rb_f_sprintf]
Tietew [email protected] wrote:

e$B$I$3$+$Ge(B len=-1 e$B$Je(B Bignum e$B$,@8@.$5$l$F$$$k$C$]$$$G$9!#e(B
gdbe$B$GC0G0$KDI$C$?$H$3$m!“e(B”%d" e$B$Ke(B 1 e$BL$K~$Ne(B Float e$B$rM?$($k$H:F8=$7e(B
e$B$^$7$?!#860x$Oe(B rb_dbl2big e$B$+!)e(B

tietew@tomoyo:~$ ruby -ve ‘p “%d” % 0.9’
ruby 1.8.6 (2007-08-07 patchlevel 5000) [x86_64-linux]
-e:1:in `%': negative allocation size (or too big) (NoMemoryError)

e$B$H$j$“$($:2<$N%Q%C%A$GD>$j$^$7$?!#e(B
e$B$h$jNI$$=$@5$,$”$j$^$7$?$iC/$+$h$m$7$/$*4j$$$7$^$9!#e(B

e$BG0$N$?$a%P%0%H%i%C%W$rIU$1$F$_$^$7$?!#e(B

Index: bignum.c

— bignum.c (e$B%j%S%8%g%se(B 12928)
+++ bignum.c (e$B:n6H%3%T!<e(B)
@@ -47,6 +47,7 @@
{
NEWOBJ(big, struct RBignum);
OBJSETUP(big, klass, T_BIGNUM);

  • if(len <= 0) rb_bug(“zero length Bignum”);
    big->sign = sign?1:0;
    big->len = len;
    big->digits = ALLOC_N(BDIGIT, len);
    @@ -885,6 +886,9 @@
    if (isnan(d)) {
    rb_raise(rb_eFloatDomainError, “NaN”);
    }

  • if ((long)u == 0) {

  • return INT2FIX(0);

  • }

    while (!POSFIXABLE(u) || 0 != (long)u) {
    u /= (double)(BIGRAD);