Pack bug on 64-bit ruby

Thanks Lyle - that seems to work although (as expected I think) it does
it in 8 bytes.

The question I have now then is, if I’ve got code that uses
[-1].pack(“V”), how should I handle this on 64 bit platforms? Is there
a way to tell the bit-ness of Ruby from within Ruby? Perhaps a
RUBY_BITNESS constant? Or is there some sort of “cross-bitness”
approach I can use?

Regards,

Dan

···

-----Original Message-----
From: Lyle Johnson [mailto:lyle@users.sourceforge.net]
Sent: Monday, November 17, 2003 2:47 PM
To: ruby-talk ML
Subject: Re: pack bug on 64-bit ruby

Daniel Berger wrote:

Looks like there’s a 64-bit related bug in pack():

irb(main):007:0> [-1].pack(“V”)
RangeError: integer 18446744073709551615 too big to convert to
unsigned int' from (irb):7:in pack’
from (irb):7

If Array#pack is supposed to output a four-character string for the
unsigned long value, I think maybe this shouldn’t work for 64-bit.
You’re passing in a value of -1, which is 2**64 - 1 when
represented as
an unsigned long on a 64-bit machine. You can’t pack that into four
characters (bytes).

Out of curiosity, what happens if you instead try this?

 [-1].pack("L_")

Note the trailing underscore. If I read the code right, this
should do
the right thing.

Hi,

···

At Tue, 18 Nov 2003 07:03:54 +0900, Berger, Daniel wrote:

The question I have now then is, if I’ve got code that uses
[-1].pack(“V”), how should I handle this on 64 bit platforms? Is there
a way to tell the bit-ness of Ruby from within Ruby? Perhaps a
RUBY_BITNESS constant? Or is there some sort of “cross-bitness”
approach I can use?

[-1].pack(“v”) gently gives “\377\377” on 32 bit platforms, so
it might be better to just mask, like as Perl.

  • pack.c (pack_pack): mask for lower bits. [ruby-talk:85377]

    Index: pack.c
    ===================================================================
    RCS file: /cvs/ruby/src/ruby/pack.c,v
    retrieving revision 1.57
    diff -u -2 -p -r1.57 pack.c
    — pack.c 9 Oct 2003 17:45:52 -0000 1.57
    +++ pack.c 18 Nov 2003 00:45:32 -0000
    @@ -676,4 +676,5 @@ pack_pack(ary, fmt)
    if (NIL_P(from)) s = 0;
    else {
  •       from = rb_funcall(from, '&', 1, INT2FIX(0xffff));
          s = NUM2INT(from);
      }
    

@@ -690,5 +691,6 @@ pack_pack(ary, fmt)
if (NIL_P(from)) l = 0;
else {

  •       l = NATINT_U32(from);
    
  •       from = rb_funcall(from, '&', 1, UINT2NUM(0xffffffff));
    
  •       l = NUM2ULONG(from);
      }
      l = htonl(l);
    

@@ -704,4 +706,5 @@ pack_pack(ary, fmt)
if (NIL_P(from)) s = 0;
else {

  •       from = rb_funcall(from, '&', 1, INT2FIX(0xffff));
          s = NUM2INT(from);
      }
    

@@ -718,5 +721,6 @@ pack_pack(ary, fmt)
if (NIL_P(from)) l = 0;
else {

  •       l = NATINT_U32(from);
    
  •       from = rb_funcall(from, '&', 1, UINT2NUM(0xffffffff));
    
  •       l = NUM2ULONG(from);
      }
      l = htovl(l);
    


Nobu Nakada

Forgive my ignorance, but does this just mean that pack(“V”) is always
32 bits, as in Perl?

Dan

···

nobu.nokada@softhome.net wrote:

Hi,

At Tue, 18 Nov 2003 07:03:54 +0900, > Berger, Daniel wrote:

The question I have now then is, if I’ve got code that uses
[-1].pack(“V”), how should I handle this on 64 bit platforms? Is there
a way to tell the bit-ness of Ruby from within Ruby? Perhaps a
RUBY_BITNESS constant? Or is there some sort of “cross-bitness”
approach I can use?

[-1].pack(“v”) gently gives “\377\377” on 32 bit platforms, so
it might be better to just mask, like as Perl.

  • pack.c (pack_pack): mask for lower bits. [ruby-talk:85377]

Index: pack.c

RCS file: /cvs/ruby/src/ruby/pack.c,v
retrieving revision 1.57
diff -u -2 -p -r1.57 pack.c
— pack.c 9 Oct 2003 17:45:52 -0000 1.57
+++ pack.c 18 Nov 2003 00:45:32 -0000
@@ -676,4 +676,5 @@ pack_pack(ary, fmt)
if (NIL_P(from)) s = 0;
else {

  •               from = rb_funcall(from, '&', 1, INT2FIX(0xffff));
                  s = NUM2INT(from);
              }
    

@@ -690,5 +691,6 @@ pack_pack(ary, fmt)
if (NIL_P(from)) l = 0;
else {

  •               l = NATINT_U32(from);
    
  •               from = rb_funcall(from, '&', 1, UINT2NUM(0xffffffff));
    
  •               l = NUM2ULONG(from);
              }
              l = htonl(l);
    

@@ -704,4 +706,5 @@ pack_pack(ary, fmt)
if (NIL_P(from)) s = 0;
else {

  •               from = rb_funcall(from, '&', 1, INT2FIX(0xffff));
                  s = NUM2INT(from);
              }
    

@@ -718,5 +721,6 @@ pack_pack(ary, fmt)
if (NIL_P(from)) l = 0;
else {

  •               l = NATINT_U32(from);
    
  •               from = rb_funcall(from, '&', 1, UINT2NUM(0xffffffff));
    
  •               l = NUM2ULONG(from);
              }
              l = htovl(l);
    


Nobu Nakada

Hi,

···

At Thu, 20 Nov 2003 00:25:03 +0900, Daniel Berger wrote:

Forgive my ignorance, but does this just mean that pack(“V”) is always
32 bits, as in Perl?

Yes, masking except lower bits.


Nobu Nakada