psych fails to load YAML containing serialized objects for which `klass.allocate` returns nil
The beaker testing library serializes a YAML file representing the configuration for a prior test run. That library can contain AWS::Core::Data objects (see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/Core/Data.html).
For example, a snippet might look like:
:placement: !ruby/object:AWS::Core::Data
data:
:availability_zone: us-west-2a
:group_name:
:tenancy: default
The problem is that AWS::Core::Data somehow manages to have its .allocate method return nil:
>> require 'aws/core/data'
=> true
>> AWS::Core::Data.allocate
=> nil
When this is de-serialized, s here becomes nil: https://github.com/tenderlove/psych/blob/master/lib/psych/visitors/to_ruby.rb#L371 and then fireworks happen here: https://github.com/tenderlove/psych/blob/master/lib/psych/visitors/to_ruby.rb#L379
The end of the stack trace looks like:
/home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/aws-sdk-v1-1.65.0/lib/aws/core/data.rb:146:in `respond_to?': undefined method `key?' for nil:NilClass (NoMethodError)
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:379:in `init_with'
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:372:in `revive'
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:207:in `visit_Psych_Nodes_Mapping'
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/visitor.rb:15:in `visit'
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/visitor.rb:5:in `accept'
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:31:in `accept'
from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:336:in `block in revive_hash'
I don't think AWS::Core::Data is being a good ruby citizen by doing whatever they're doing with .allocate; but perhaps the error thrown here good be more intuitive. We may work around this with a to_yaml at serialization time (or something similar), but figured this was worth reporting.
Wow. Yes, this doesn't seem like a good thing. We could probably unbind the real allocate method and bind it to that object. I'll try to think of something.
Thanks for reporting this!
Aaron Patterson http://tenderlovemaking.com/ I'm on an iPhone so I apologize for top posting.
On Sep 2, 2015, at 11:18 PM, Rick Bradley [email protected] wrote:
The beaker testing library serializes a YAML file representing the configuration for a prior test run. That library can contain AWS::Core::Data objects (see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/Core/Data.html).
For example, a snippet might look like:
:placement: !ruby/object:AWS::Core::Data data: :availability_zone: us-west-2a :group_name: :tenancy: defaultThe problem is that AWS::Core::Data somehow manages to have its .allocate method return nil:
require 'aws/core/data' => true AWS::Core::Data.allocate => nil When this is de-serialized, s here becomes nil: https://github.com/tenderlove/psych/blob/master/lib/psych/visitors/to_ruby.rb#L371 and then fireworks happen here: https://github.com/tenderlove/psych/blob/master/lib/psych/visitors/to_ruby.rb#L379
The end of the stack trace looks like:
/home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/aws-sdk-v1-1.65.0/lib/aws/core/data.rb:146:in
respond_to?': undefined methodkey?' for nil:NilClass (NoMethodError) from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:379:ininit_with' from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:372:inrevive' from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:207:invisit_Psych_Nodes_Mapping' from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/visitor.rb:15:invisit' from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/visitor.rb:5:inaccept' from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:31:inaccept' from /home/rick/pl/pe_acceptance_tests/vendor/ruby/gems/psych-2.0.15/lib/psych/visitors/to_ruby.rb:336:in `block in revive_hash' I don't think AWS::Core::Data is being a good ruby citizen by doing whatever they're doing with .allocate; but perhaps the error thrown here good be more intuitive. We may work around this with a to_yaml at serialization time (or something similar), but figured this was worth reporting.― Reply to this email directly or view it on GitHub.
Scrolling through the issues, I hit this. I really cannot see how this is Psych's concern. Class.new calls klass.allocate.initialize. If klass.allocate returns nil, then many, many things are expected to break. For some library to know what another library or application intends that instead resulted in this nil is simply not possible. If you want to use Psych to deserialize such an object, you will have to provide the necessary code to handle the matter.