Jira (PUP-10029) A Puppet::DataTypes::Error#to_s() fails with a stack overflow

18 views
Skip to first unread message

Joshua Partlow (JIRA)

unread,
Sep 23, 2019, 6:28:03 PM9/23/19
to puppe...@googlegroups.com
Joshua Partlow created an issue
 
Puppet / Bug PUP-10029
A Puppet::DataTypes::Error#to_s() fails with a stack overflow
Issue Type: Bug Bug
Affects Versions: PUP 6.10.0
Assignee: Unassigned
Created: 2019/09/23 3:27 PM
Priority: Normal Normal
Reporter: Joshua Partlow

Puppet Version: 6.10 (master)

Instances of Puppet::DataTypes::Error end up recursively overflowing the stack calling to_s().

[root@wuh7cxdfusfnult installer]# /opt/puppetlabs/puppet/bin/puppet --version
6.10.0
[root@wuh7cxdfusfnult installer]# /opt/puppetlabs/puppet/bin/irb
irb(main):001:0> require 'puppet'
r=> true
irb(main):002:0> require 'puppet/datatypes/impl/error'
=> true
irb(main):003:0> e = Puppet::DataTypes::Error.new('foo')
=> #<Puppet::DataTypes::Error:0x00000000024d9c50 @msg="foo", @kind=nil, @details=nil, @issue_code=nil>
irb(main):004:0> e.to_s
Traceback (most recent call last):
       16: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/string_converter.rb:602:in `string_PRuntimeType'
       15: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/datatypes/impl/error.rb:38:in `to_s'
       14: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/string_converter.rb:485:in `convert'
       13: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:130:in `infer_set'
       12: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:272:in `infer_set'
       11: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:253:in `infer'
       10: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/visitor.rb:83:in `visit_this_0'
        9: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:519:in `infer_Object'
        8: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:519:in `new'
        7: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/p_runtime_type.rb:33:in `initialize'
        6: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_asserter.rb:33:in `assert_instance_of'
        5: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:2991:in `instance?'
        4: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:2991:in `any?'
        3: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:2991:in `block in instance?'
        2: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:1551:in `instance?'
        1: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:1027:in `instance?'
SystemStackError (stack level too deep)
irb(main):005:0> 

This turned up while I was working with Bolt apply(), and had captured an error before calling a new apply(). The Bolt Applicator transforms a catalog_input Hash to JSON here. Part of that input hash are existing variables in the plan. If one of those variables is a stored error from a previous apply, for example, it fails here when to_json calls to_s on it...

Add Comment Add Comment
 
This message was sent by Atlassian JIRA (v7.7.1#77002-sha1:e75ca93)
Atlassian logo

Joshua Partlow (JIRA)

unread,
Sep 23, 2019, 6:30:03 PM9/23/19
to puppe...@googlegroups.com
Joshua Partlow commented on Bug PUP-10029
 
Re: A Puppet::DataTypes::Error#to_s() fails with a stack overflow

Henrik Lindberg Hi there; bumped into this while working with Bolt apply(). Looks like Puppet::DataTypes::Error.to_s() is broken, or something else is going on that I'm not following...getting an isolated instance of Puppet::DataTypes::Error to test against wasn't straight forward .

Henrik Lindberg (JIRA)

unread,
Sep 24, 2019, 1:23:02 AM9/24/19
to puppe...@googlegroups.com

Thomas Hallgren (JIRA)

unread,
Sep 24, 2019, 8:29:02 AM9/24/19
to puppe...@googlegroups.com

The code doesn't understand that Puppet::Datatypes::Error is a known type. Does the same thing happen if you precede this with require 'puppet/datatypes' (that's where the type registration happens)?

Joshua Partlow (JIRA)

unread,
Sep 24, 2019, 12:20:03 PM9/24/19
to puppe...@googlegroups.com

Hi Thomas Hallgren, yeah, I was originally trying to require 'puppet/datatypes/error', but that has some add behavior, see below:

[root@wuh7cxdfusfnult ~]# /opt/puppetlabs/puppet/bin/irb 
irb(main):001:0> require 'puppet'
=> true
irb(main):002:0> require 'puppet/datatypes'
=> false
irb(main):003:0> require 'puppet/datatypes/error'
Traceback (most recent call last):
        7: from /opt/puppetlabs/puppet/bin/irb:11:in `<main>'
        6: from (irb):3
        5: from /opt/puppetlabs/puppet/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
        4: from /opt/puppetlabs/puppet/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
        3: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/datatypes/error.rb:1:in `<top (required)>'
        2: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/datatypes.rb:124:in `create_type'
        1: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/datatypes.rb:133:in `rescue in create_type'
ArgumentError (Data Type Load Error for type 'Error': undefined method `register_implementation' for nil:NilClass)
irb(main):004:0> e = Puppet::DataTypes::Error.new('foo')
=> #<Puppet::DataTypes::Error:0x0000000003af3a68 @msg="foo", @kind=nil, @details=nil, @issue_code=nil>
irb(main):005:0> e.to_s
Traceback (most recent call last):
       16: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/string_converter.rb:602:in `string_PRuntimeType'
       15: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/datatypes/impl/error.rb:38:in `to_s'
       14: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/string_converter.rb:485:in `convert'
       13: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:130:in `infer_set'
       12: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:272:in `infer_set'
       11: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:253:in `infer'
       10: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/visitor.rb:83:in `visit_this_0'
        9: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:519:in `infer_Object'
        8: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_calculator.rb:519:in `new'
        7: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/p_runtime_type.rb:33:in `initialize'
        6: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/type_asserter.rb:33:in `assert_instance_of'
        5: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:2991:in `instance?'
        4: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:2991:in `any?'
        3: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:2991:in `block in instance?'
        2: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:1551:in `instance?'
        1: from /opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/pops/types/types.rb:1027:in `instance?'
SystemStackError (stack level too deep)

Henrik Lindberg (JIRA)

unread,
Sep 24, 2019, 12:46:03 PM9/24/19
to puppe...@googlegroups.com

Joshua Partlow That means there are no loaders bound in the puppet context. The logic you are executing ends up in this method to get the
implementation registry - and since there are no loaders in the context you end up with the nil loaders.

def self.implementation_registry
  loaders = Puppet.lookup(:loaders) { nil }
  loaders.nil? ? nil : loaders.implementation_registry
end

You can probably initialize it like apply does - like this:

    env = Puppet.lookup(:environments).get(Puppet[:environment])
    Puppet.override(:current_environment => env, :loaders => Puppet::Pops::Loaders.new(env)) do
      # Do your stuff here
    end

Joshua Partlow (JIRA)

unread,
Sep 24, 2019, 12:56:03 PM9/24/19
to puppe...@googlegroups.com

Hmm, that's interesting, that does work:

[root@wuh7cxdfusfnult ~]# cat test.rb 
require 'puppet'
Puppet.initialize_settings
env = Puppet.lookup(:environments).get(Puppet[:environment])
Puppet.override(:current_environment => env, :loaders => Puppet::Pops::Loaders.new(env)) do
  require 'puppet/datatypes/error'
  e = Puppet::DataTypes::Error.new('foo')
  puts e.to_s 
end
[root@wuh7cxdfusfnult ~]# /opt/puppetlabs/puppet/bin/ruby test.rb
Error({'msg' => 'foo'})

So the issue I'm seeing appears to be a case of Bolt handling an error instance outside of a context with loaders available, here.

Unless you consider the Puppet::DataTypes::Error.to_s requiring loaders a bug in and of itself?

Joshua Partlow (JIRA)

unread,
Sep 24, 2019, 1:32:04 PM9/24/19
to puppe...@googlegroups.com

Josh Cooper (JIRA)

unread,
Sep 24, 2019, 2:39:03 PM9/24/19
to puppe...@googlegroups.com
Josh Cooper commented on Bug PUP-10029

I'd expect puppet to fail more gracefully if there isn't a current environment.

Rob Braden (JIRA)

unread,
Sep 30, 2019, 12:51:04 PM9/30/19
to puppe...@googlegroups.com

Josh Cooper (Jira)

unread,
Jan 27, 2021, 1:43:04 PM1/27/21
to puppe...@googlegroups.com
Josh Cooper commented on Bug PUP-10029
 
Re: A Puppet::DataTypes::Error#to_s() fails with a stack overflow

I believe this was fixed in PUP-10221, so closing this as a duplicate. Please reopen if I've missed something.

This message was sent by Atlassian Jira (v8.5.2#805002-sha1:a66f935)
Atlassian logo
Reply all
Reply to author
Forward
0 new messages