From 7fe7b7bc5a7a3d79280c9dbf2a2383d386386b0f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 26 Nov 2023 00:28:36 +0900 Subject: [PATCH] Fix portability of bignum in ISeq Binary Format - Unless `sizeof(BDIGIT) == 4`, (8-byte integer not available), the size to be loaded was wrong. - Since `BDIGIT`s are dumped as raw binary, the loaded byte order was inverted unless little-endian. --- compile.c | 8 ++++++-- test/ruby/test_iseq.rb | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/compile.c b/compile.c index 6038a22723..7e8b6c37b8 100644 --- a/compile.c +++ b/compile.c @@ -12859,8 +12859,12 @@ ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_head const struct ibf_object_bignum *bignum = IBF_OBJBODY(struct ibf_object_bignum, offset); int sign = bignum->slen > 0; ssize_t len = sign > 0 ? bignum->slen : -1 * bignum->slen; - VALUE obj = rb_integer_unpack(bignum->digits, len * 2, 2, 0, - INTEGER_PACK_LITTLE_ENDIAN | (sign == 0 ? INTEGER_PACK_NEGATIVE : 0)); + const int big_unpack_flags = /* c.f. rb_big_unpack() */ + INTEGER_PACK_LSWORD_FIRST | + INTEGER_PACK_NATIVE_BYTE_ORDER; + VALUE obj = rb_integer_unpack(bignum->digits, len, sizeof(BDIGIT), 0, + big_unpack_flags | + (sign == 0 ? INTEGER_PACK_NEGATIVE : 0)); if (header->internal) rb_obj_hide(obj); if (header->frozen) rb_obj_freeze(obj); return obj; diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index 6a1a1ea8c1..f05d067ac2 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -791,4 +791,11 @@ class TestISeq < Test::Unit::TestCase end end; end + + def test_ibf_bignum + iseq = RubyVM::InstructionSequence.compile("0x0"+"_0123_4567_89ab_cdef"*5) + expected = iseq.eval + result = RubyVM::InstructionSequence.load_from_binary(iseq.to_binary).eval + assert_equal expected, result, proc {sprintf("expected: %x, result: %x", expected, result)} + end end