Skip to content

Incorrect deserialization of some instances serialized by version 0.2.0  #52

@aalong-tr

Description

@aalong-tr

In the ruby 2 version of OpenStruct, serialized objects can have two root keys: table and modifiable. The second key only seems to appear after an attribute is assigned post-initialization:

irb(main):012:0> OpenStruct::VERSION
=> "0.2.0"
irb(main):013:0> RUBY_VERSION
=> "2.7.5"
irb(main):014:0> s = OpenStruct.new(foo: 1, bar: 'baz')
=> #<OpenStruct foo=1, bar="baz">
irb(main):015:0> Psych.dump s
=> "--- !ruby/object:OpenStruct\ntable:\n  :foo: 1\n  :bar: baz\n"
irb(main):017:0> s.bar = 'baz'
=> "baz"
irb(main):019:0> Psych.dump s
=> "--- !ruby/object:OpenStruct\ntable:\n  :foo: 1\n  :bar: baz\nmodifiable: true\n"

On newer versions of OpenStruct, serialized objects with that key are not deserialized as expected:

irb(main):010:0> OpenStruct::VERSION
=> "0.3.1"
irb(main):011:0> RUBY_VERSION
=> "3.0.5"
irb(main):012:0> s = Psych.load "--- !ruby/object:OpenStruct\ntable:\n  :foo: 1\n  :bar: baz\nmodifiable: true\n"
=> #<OpenStruct table={:foo=>1, :bar=>"baz"}, modifiable=true>
irb(main):013:0> s.foo
=> nil

The deserialization hook provided by OpenStruct attempts to be backwards compatible, but incorrectly assumes that legacy documents have exactly one root-level key table:
https://github.com/ruby/ostruct/blob/master/lib/ostruct.rb#L449-L454

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions