[MacRuby-devel] [MacRuby] #159: "%d" with large integer argument gives conversion error

MacRuby ruby-noreply at macosforge.org
Fri Dec 11 18:17:38 PST 2009


#159: "%d" with large integer argument gives conversion error
---------------------------------+------------------------------------------
 Reporter:  jamis@…              |       Owner:  lsansonetti@…        
     Type:  defect               |      Status:  new                  
 Priority:  major                |   Milestone:                       
Component:  MacRuby              |    Keywords:                       
---------------------------------+------------------------------------------

Old description:

> The following script reproduces the error easily:
>
> {{{
> N = 34363859232
> p N
> p N.class
>
> puts "%d" % N
> }}}
>
> This results in the following exception:
>
> {{{
> 01.rb:5:in `%': integer 34363859232 too big to convert to `int'
> (RangeError)
> }}}
>
> When run in ruby 1.9, the output shows that N is a Bignum. When run in
> macruby, the output shows that N is a fixnum. This appears to be due to
> bignum.c line 523:
>
> {{{
>     if (len <= (sizeof(long)*CHAR_BIT)) {
> }}}
>
> Apparently, in macruby, sizeof(long) is 8, which means bignums are only
> instantiated for integers larger than 64 bits or so, and in the above
> example, the integer is only 44 bits.
>
> Even though the bignums are only created based on sizeof(long), the
> rb_str_format function in sprintf.c uses FIX2LONG for converting the
> VALUE to a long int, and FIX2LONG uses INT_MIN and INT_MAX to check the
> bounds of the integer.
>
> I'm not sure what the safest way to fix this is. Should check_int (and
> others?) in numeric.c be comparing against larger boundary numbers,
> instead of INT_MIN/MAX?

New description:

 [[BR]]
 The following script reproduces the error easily:

 {{{
 N = 34363859232
 p N
 p N.class

 puts "%d" % N
 }}}

 This results in the following exception:

 {{{
 01.rb:5:in `%': integer 34363859232 too big to convert to `int'
 (RangeError)
 }}}

 When run in ruby 1.9, the output shows that N is a Bignum. When run in
 macruby, the output shows that N is a fixnum. This appears to be due to
 bignum.c line 523:

 {{{
     if (len <= (sizeof(long)*CHAR_BIT)) {
 }}}

 Apparently, in macruby, sizeof(long) is 8, which means bignums are only
 instantiated for integers larger than 64 bits or so, and in the above
 example, the integer is only 44 bits.

 Even though the bignums are only created based on sizeof(long), the
 rb_str_format function in sprintf.c uses FIX2LONG for converting the VALUE
 to a long int, and FIX2LONG uses INT_MIN and INT_MAX to check the bounds
 of the integer.

 I'm not sure what the safest way to fix this is. Should check_int (and
 others?) in numeric.c be comparing against larger boundary numbers,
 instead of INT_MIN/MAX?

--

Comment(by emoy@…):

 Part 3 of 3

 While I was at it, I added %@ to be compatible with CF/Objective-C.  I
 even added %a for hex float conversion.  I noticed that marshal.c uses %g,
 plus a save_mantissa()/load_mantissa() routine; that should someday be
 replaced with just using %a for exact conversion.

 Once we have %a:

 {{{
 % macruby -e 'puts "%a" % 1.23456789'
 0x1.3c0ca4283de18p+0
 }}}

 but:

 {{{
 % macruby -e 'puts "0x1.3c0ca4283de18p+0".to_f'
 0.0
 }}}

 This is because util.c has an old version of David M. Gay's strtod that
 doesn't know about hex floats.  But since Mac OS X has a recent version of
 Gay's strtod, if we just use the libSystem version (and save code space
 not having our own implementation), it now works:

 {{{
 % macruby -e 'puts "0x1.3c0ca4283de18p+0".to_f'
 1.23456789
 }}}

 Even more:

 {{{
 % macruby -e 'puts "inf".to_f'
 Infinity
 % macruby -e 'puts "nan".to_f'
 NaN
 }}}

 One other benefit of using the ruby sprintf code, is that it supports
 named hash arguments, like:

 {{{
 % macruby -e 'x={"a"=>[1,"foo"],"b"=>2};puts "%<b>d %{a}" % x'
 2 [1, "foo"]
 }}}

 So I attached my test program, as test-sprintf.rb and the diffs, as
 ticket159.diff.  I've also create a SVN branch:

 http://svn.macosforge.org/repository/ruby/MacRuby/branches/ticket159

 with the changes (made from yesterday's trunk).

-- 
Ticket URL: <http://www.macruby.org/trac/ticket/159#comment:5>
MacRuby <http://macruby.org/>



More information about the MacRuby-devel mailing list