Skip to content

Commit

Permalink
Merge pull request #2402 from herwinw/marshal_load_object_link
Browse files Browse the repository at this point in the history
Fix object links in Marshal.load
  • Loading branch information
herwinw committed Dec 17, 2024
2 parents 339f26b + b741d9e commit 0bb9af3
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 47 deletions.
38 changes: 14 additions & 24 deletions spec/core/marshal/shared/load.rb
Original file line number Diff line number Diff line change
Expand Up @@ -393,11 +393,9 @@
str = "string"

# this string represents: [<#UserDefinedImmediate A>, <#String "string">, <#String "string">]
NATFIXME 'loads an array containing an instance of the object, followed by multiple instances of another object', exception: ArgumentError, message: 'dump format error' do
marshaled_obj = Marshal.send(@method, "\004\b[\bu:\031UserDefinedImmediate\000\"\vstring@\a")
marshaled_obj = Marshal.send(@method, "\004\b[\bu:\031UserDefinedImmediate\000\"\vstring@\a")

marshaled_obj.should == [nil, str, str]
end
marshaled_obj.should == [nil, str, str]
end

it "loads any structure with multiple references to the same object, followed by multiple instances of another object" do
Expand Down Expand Up @@ -554,12 +552,10 @@
s.instance_variable_set(:@foo, 10)
obj = ['5', s, 'hi'].extend(Meths, MethsMore)
obj.instance_variable_set(:@mix, s)
NATFIXME 'loads an array having ivar', exception: ArgumentError, message: 'dump format error' do
new_obj = Marshal.send(@method, "\004\bI[\b\"\0065I\"\twell\006:\t@fooi\017\"\ahi\006:\t@mix@\a")
new_obj.should == obj
new_obj.instance_variable_get(:@mix).should equal new_obj[1]
new_obj[1].instance_variable_get(:@foo).should == 10
end
new_obj = Marshal.send(@method, "\004\bI[\b\"\0065I\"\twell\006:\t@fooi\017\"\ahi\006:\t@mix@\a")
new_obj.should == obj
new_obj.instance_variable_get(:@mix).should equal new_obj[1]
new_obj[1].instance_variable_get(:@foo).should == 10
end

it "loads an extended Array object containing a user-marshaled object" do
Expand Down Expand Up @@ -733,9 +729,7 @@
it "loads a string having ivar with ref to self" do
obj = +'hi'
obj.instance_variable_set(:@self, obj)
NATFIXME 'loads a string having ivar with ref to self', exception: ArgumentError, message: 'dump format error' do
Marshal.send(@method, "\004\bI\"\ahi\006:\n@self@\000").should == obj
end
Marshal.send(@method, "\004\bI\"\ahi\006:\n@self@\000").should == obj
end

it "loads a string through StringIO stream" do
Expand Down Expand Up @@ -919,13 +913,11 @@ def io.binmode; raise "binmode"; end
obj = Exception.new("foo")
obj.instance_variable_set :@arr, arr

NATFIXME 'Support ivar', exception: ArgumentError, message: 'dump format error' do
loaded = Marshal.send(@method, "\x04\bo:\x0EException\b:\tmesg\"\bfoo:\abt0:\t@arr[\t:\aso;\t\"\ahi@\b")
new_arr = loaded.instance_variable_get :@arr
loaded = Marshal.send(@method, "\x04\bo:\x0EException\b:\tmesg\"\bfoo:\abt0:\t@arr[\t:\aso;\t\"\ahi@\b")
new_arr = loaded.instance_variable_get :@arr

loaded.message.should == obj.message
new_arr.should == arr
end
loaded.message.should == obj.message
new_arr.should == arr
end
end

Expand All @@ -952,12 +944,10 @@ def io.binmode; raise "binmode"; end
obj = Object.new
obj.instance_variable_set :@str, arr

NATFIXME 'Support ivar', exception: ArgumentError, message: 'dump format error' do
new_obj = Marshal.send(@method, "\004\bo:\vObject\006:\t@str[\t:\aso;\a\"\ahi@\a")
new_str = new_obj.instance_variable_get :@str
new_obj = Marshal.send(@method, "\004\bo:\vObject\006:\t@str[\t:\aso;\a\"\ahi@\a")
new_str = new_obj.instance_variable_get :@str

new_str.should == arr
end
new_str.should == arr
end

it "loads an Object with a non-US-ASCII instance variable" do
Expand Down
61 changes: 38 additions & 23 deletions src/marshal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ class Reader
def initialize(source)
@source = source
@symbol_lookup = []
@object_lookup = []
end

def read_byte
Expand All @@ -435,6 +436,11 @@ def read_version
end
end

def read_object_link
index = read_integer
@object_lookup.fetch(index)
end

def read_signed_byte
byte = read_byte
byte > 127 ? (byte - 256) : byte
Expand Down Expand Up @@ -644,44 +650,53 @@ def read_value
true
when 'F'
false
when '@'
read_object_link
when 'i'
read_integer
when 'l'
read_big_integer
when '"'
read_string
when ':'
read_symbol
when ';'
read_symbol_link
when 'f'
read_float
when '['
read_array
when '{'
read_hash
when '}'
read_hash_with_default
when 'c'
read_class
when 'm'
read_module
when '/'
read_regexp
when 'U'
read_user_marshaled_object_with_allocate
when 'u'
read_user_marshaled_object_without_allocate
when 'S'
read_struct
when 'o'
read_object
when 'I'
result = read_value
read_ivars(result) unless result.is_a?(Regexp)
result
else
raise ArgumentError, 'dump format error'
index = @object_lookup.size
@object_lookup << nil # placeholder
value = case char
when '"'
read_string
when '['
read_array
when '{'
read_hash
when '}'
read_hash_with_default
when 'c'
read_class
when 'm'
read_module
when '/'
read_regexp
when 'U'
read_user_marshaled_object_with_allocate
when 'u'
read_user_marshaled_object_without_allocate
when 'S'
read_struct
when 'o'
read_object
else
raise ArgumentError, 'dump format error'
end
@object_lookup[index] = value
value
end
end

Expand Down

0 comments on commit 0bb9af3

Please sign in to comment.