Skip to content

Commit ebcafc9

Browse files
committed
[GR-42999] Fix Marshal.dump with 4-8 bytes Integer
PullRequest: truffleruby/3582
2 parents 03d1124 + 4181c33 commit ebcafc9

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Bug fixes:
44

55
* Fix `rb_thread_fd_select()` to correctly initialize fdset copies and handle the timeout (@eregon).
6+
* Fix `Marshal.dump` when big Integer (that cannot be expressed with 4 bytes) is serialized (#2790, @andrykonchin).
67

78
# 22.3.0
89

spec/ruby/core/marshal/dump_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,20 @@
185185
[Marshal, -2**64, "\004\bl-\n\000\000\000\000\000\000\000\000\001\000"],
186186
].should be_computed_by(:dump)
187187
end
188+
189+
it "increases the object links counter" do
190+
obj = Object.new
191+
object_1_link = "\x06" # representing of (0-based) index=1 (by adding 5 for small Integers)
192+
object_2_link = "\x07" # representing of index=2
193+
194+
# objects: Array, Object, Object
195+
Marshal.dump([obj, obj]).should == "\x04\b[\ao:\vObject\x00@#{object_1_link}"
196+
197+
# objects: Array, Bignum, Object, Object
198+
Marshal.dump([2**64, obj, obj]).should == "\x04\b[\bl+\n\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
199+
Marshal.dump([2**48, obj, obj]).should == "\x04\b[\bl+\t\x00\x00\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
200+
Marshal.dump([2**32, obj, obj]).should == "\x04\b[\bl+\b\x00\x00\x00\x00\x01\x00o:\vObject\x00@#{object_2_link}"
201+
end
188202
end
189203

190204
describe "with a String" do

src/main/ruby/truffleruby/core/marshal.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,9 @@ def const_lookup(name, type = nil)
542542
end
543543

544544
def add_non_immediate_object(obj)
545-
return if Primitive.immediate_value?(obj)
545+
# Skip entities that cannot be referenced as objects.
546+
# Integers that are bigger than 4 bytes also increase the object links counter.
547+
return if Primitive.immediate_value?(obj) && !serialize_as_bignum?(obj)
546548
add_object(obj)
547549
end
548550

@@ -1060,13 +1062,18 @@ def serialize_instance_variables(obj, ivars)
10601062
end
10611063

10621064
def serialize_integer(n, prefix = nil)
1063-
if Truffle::Type.fits_into_int?(n)
1065+
if !serialize_as_bignum?(n)
10641066
Truffle::Type.binary_string(prefix.to_s + serialize_fixnum(n))
10651067
else
10661068
serialize_bignum(n)
10671069
end
10681070
end
10691071

1072+
# Integers bigger than 4 bytes are serialized in a special format
1073+
def serialize_as_bignum?(obj)
1074+
Primitive.object_kind_of?(obj, Integer) && !Truffle::Type.fits_into_int?(obj)
1075+
end
1076+
10701077
def serialize_fixnum(n)
10711078
if n == 0
10721079
s = n.chr

0 commit comments

Comments
 (0)