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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions