Project

General

Profile

Bug #1131

String#unpack("V") does not work correctly is linux on s390x

Added by ittayd (Ittay Dror) over 10 years ago. Updated over 8 years ago.

Status:
Closed
Priority:
Normal
ruby -v:
ruby 1.8.7 (2008-08-11 patchlevel 72) [s390x-linux]
[ruby-core:21937]

Description

=begin
irb(main):008:0> [17138429].pack("V").unpack("V")
=> [73608992059817984]

ruby --version:
ruby 1.8.7 (2008-08-11 patchlevel 72) [s390x-linux]

uname -a:
Linux etpgloi 2.6.5-7.244-s390x #1 SMP Mon Dec 12 18:32:25 UTC 2005 s390x s390x s390x GNU/Linux

cat /etc/issue:
Welcome to SUSE LINUX Enterprise Server 9 (s390x) - Kernel \r (\l).

ruby was compiled from sources.
=end


Files

config.h (5.12 KB) config.h config.h from system-z (running linux) ittayd (Ittay Dror), 04/16/2009 03:41 PM
s390x-config.h (4.89 KB) s390x-config.h s390x config.h darix (Marcus Rückert), 02/16/2010 07:51 PM
bnc603914_string_unpack.patch (485 Bytes) bnc603914_string_unpack.patch Proposed patch kkaempf (Klaus Kämpf), 05/10/2010 03:48 AM

History

#1

Updated by ittayd (Ittay Dror) over 10 years ago

=begin
the following workaround fixes the issue:
if [1].pack('V').unpack('V')[0] != 1
class String
alias_method :broken_unpack, :unpack
def unpack(spec)
broken_unpack(spec).each_with_index.map do |x,i|
if spec[i] == ?V
x = x / 4294967296 # 256 ^ 4
end
x
end
end
end
end
=end

#2

Updated by nobu (Nobuyoshi Nakada) over 10 years ago

=begin
Hi,

At Sun, 8 Feb 2009 22:31:10 +0900,
Ittay Dror wrote in [ruby-core:21937]:

ruby -v: ruby 1.8.7 (2008-08-11 patchlevel 72) [s390x-linux]

irb(main):008:0> [17138429].pack("V").unpack("V")
=> [73608992059817984]

ruby --version:
ruby 1.8.7 (2008-08-11 patchlevel 72) [s390x-linux]

System Z is 64bit big endian? Could you show the config.h?

--
Nobu Nakada

=end

#3

Updated by ittayd (Ittay Dror) over 10 years ago

=begin

=end

#4

Updated by naruse (Yui NARUSE) almost 10 years ago

  • Status changed from Open to Assigned
  • Assignee set to nobu (Nobuyoshi Nakada)

=begin

=end

#5

Updated by darix (Marcus Rückert) over 9 years ago

=begin
any update on this bug?
=end

#6

Updated by matz (Yukihiro Matsumoto) over 9 years ago

=begin
Hi,

In message "Re: [ruby-core:28176] [Bug #1131] String#unpack("V") does not work correctly is linux on s390x"
on Mon, 15 Feb 2010 20:05:55 +0900, Marcus Rückert redmine@ruby-lang.org writes:

|any update on this bug?

Since no core developer has s390x machine, we need information asked
in [ruby-core:21940] to solve the problem. Or patch from the owner is
welcome.

                        matz.

=end

#7

Updated by darix (Marcus Rückert) over 9 years ago

=begin
another s390x config.h
=end

#8

Updated by darix (Marcus Rückert) over 9 years ago

=begin
On 2010-02-16 10:15:28 +0900, Yukihiro Matsumoto wrote:

In message "Re: [ruby-core:28176] [Bug #1131] String#unpack("V") does not work correctly is linux on s390x"
on Mon, 15 Feb 2010 20:05:55 +0900, Marcus Rückert redmine@ruby-lang.org writes:

|any update on this bug?

Since no core developer has s390x machine, we need information asked
in [ruby-core:21940] to solve the problem. Or patch from the owner is
welcome.

04/16/2009 03:41 PM - Ittay Dror
File config.h added

it just seems that event didnt trigger an email.
i now also attached our config.h.

If you need any testing for patches let me know.

 darix

--
openSUSE - SUSE Linux is my linux
openSUSE is good for you
www.opensuse.org

=end

#9

Updated by kkaempf (Klaus Kämpf) over 9 years ago

=begin
unpack("V") broken on 64bit big endian systems, ppc64 is also affected.

It is caused by the following code (pack.c, pack_unpack(), case 'V')

             unsigned long tmp = 0;
             memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
             s += NATINT_LEN(long,4);
             rb_ary_push(ary, ULONG2NUM(vtohl(tmp)));

The use of OFF32 in memcpy copies the int32 value into the correct half of the 8-byte target value (tmp).
The call to vtohl() swaps the complete 8-byte value (acting like swap64), thereby bringing the 4 bytes of the int32
into the right endianess but also into the wrong half of the 8-byte target.

The fix is to either drop of OFF32 call or to replace the vtohl with swap32. I choose the latter since swap32
is faster than vtohl.

Proposed patch attached
=end

#10

Updated by kkaempf (Klaus Kämpf) over 9 years ago

=begin
A similar problem exists in "Array#pack"ing 'i_' values in big endian system.

[1].pack("i_")
=> "\000\000\000\000"

Again, the wrong use of OFF32() causes this bug together with the use of "long" when handling 'i' type in pack.c

I have opened a new issue for this: http://redmine.ruby-lang.org/issues/show/3297
=end

#11

Updated by akr (Akira Tanaka) over 9 years ago

=begin
ruby 1.8.8dev doesn't use OFF32() now.
=end

#12

Updated by shyouhei (Shyouhei Urabe) over 9 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r28220.
Ittay, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF