Project

General

Profile

Actions

Bug #18141

closed

Marshal load with proc yield objects before they are fully initialized

Added by byroot (Jean Boussier) about 1 year ago. Updated 10 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:105104]

Description

I assume this is a bug because I can't find any spec or test for this behaviour:

Consider the following script:

payload = Marshal.dump("foo")

Marshal.load(payload, -> (obj) {
  if obj.is_a?(String)
    p [obj, obj.encoding]
  end
  obj
})
p [:final, string, string.encoding]

outputs:

["foo", #<Encoding:ASCII-8BIT>]
[:final, "foo", #<Encoding:UTF-8>]

So Marshal call the proc before the string get its encoding assigned, this is because the encoding is stored alongside as a TYPE_IVAR. I think in such cases Marshal should delay calling the proc until the object is fully restored.

A corollary to this behaviour is that the following code:

Marshal.load(payload, :freeze.to_proc)

raises with can't modify frozen String: "foo" (FrozenError).

The same happens with any instance variable on Array or Hash

foo = {}
foo.instance_variable_set(:@bar, 42)

payload = Marshal.dump(foo)

object = Marshal.load(payload, ->(obj) {
  if obj.is_a?(Hash)
    p [obj, obj.instance_variable_get(:@bar)]
    obj.freeze
  end
  obj
})
[{}, nil]
/tmp/marshal.rb:6:in `load': can't modify frozen Hash: {} (FrozenError)
	from /tmp/marshal.rb:6:in `<main>
Actions

Also available in: Atom PDF