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.
This commit is contained in:
Nobuyoshi Nakada 2023-11-26 00:28:36 +09:00
parent 003f06bde4
commit 7fe7b7bc5a
No known key found for this signature in database
GPG Key ID: 3582D74E1FEE4465
2 changed files with 13 additions and 2 deletions

View File

@ -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;

View File

@ -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