commit 8d10ccb5116945b0f181f4a76f2f421ba3954ad9 Author: Jesse Hathaway Date: Mon Apr 17 16:07:08 2023 -0500 safe diff --git a/lib/puppet/util/storage.rb b/lib/puppet/util/storage.rb index 713f650f2a..5528885945 100644 --- a/lib/puppet/util/storage.rb +++ b/lib/puppet/util/storage.rb @@ -55,7 +55,7 @@ class Puppet::Util::Storage end Puppet::Util.benchmark(:debug, "Loaded state in %{seconds} seconds") do begin - @@state = Puppet::Util::Yaml.load_file(filename) + @@state = Puppet::Util::Yaml.safe_load_file(filename, [Symbol, Time]) rescue Puppet::Util::Yaml::YamlLoadError => detail Puppet.err _("Checksumfile %{filename} is corrupt (%{detail}); replacing") % { filename: filename, detail: detail } diff --git a/lib/puppet/util/yaml.rb b/lib/puppet/util/yaml.rb index 272086cfef..b2511ba6ac 100644 --- a/lib/puppet/util/yaml.rb +++ b/lib/puppet/util/yaml.rb @@ -9,6 +9,47 @@ module Puppet::Util::Yaml class YamlLoadError < Puppet::Error; end + # Safely load the content as YAML. By default only the following + # classes can be deserialized: + # + # * TrueClass + # * FalseClass + # * NilClass + # * Numeric + # * String + # * Array + # * Hash + # + # Attempting to deserialize other classes will raise an YamlLoadError + # exception unless they are specified in the array of *allowed_classes*. + # @param [String] yaml The yaml content to parse. + # @param [Array] allowed_classes Additional list of classes that can be deserialized. + # @param [String] filename The filename to load from, used if an exception is raised. + # @raise [YamlLoadException] If deserialization fails. + # @return The parsed YAML, which can be Hash, Array or scalar types. + def self.safe_load(yaml, allowed_classes = [], filename = nil) + if Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0') + data = YAML.safe_load(yaml, permitted_classes: allowed_classes, aliases: true, filename: filename) + else + data = YAML.safe_load(yaml, allowed_classes, [], true, filename) + end + data = false if data.nil? + data + rescue ::Psych::DisallowedClass => detail + path = filename ? "(#{filename})" : "()" + raise YamlLoadError.new("#{path}: #{detail.message}", detail) + rescue *YamlLoadExceptions => detail + raise YamlLoadError.new(detail.message, detail) + end + + # Safely load the content from a file as YAML. + # + # @see Puppet::Util::Yaml.safe_load + def self.safe_load_file(filename, allowed_classes = []) + yaml = Puppet::FileSystem.read(filename, :encoding => 'bom|utf-8') + safe_load(yaml, allowed_classes, filename) + end + def self.load_file(filename, default_value = false, strip_classes = false) if(strip_classes) then data = YAML::parse_file(filename)