diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb index da6e72f5936e..f4d335ee4f8b 100644 --- a/lib/rubygems/yaml_serializer.rb +++ b/lib/rubygems/yaml_serializer.rb @@ -423,9 +423,7 @@ class Builder MAX_ALIAS_RESOLUTIONS = 1_000 def initialize(permitted_classes: [], permitted_symbols: [], aliases: true) - @permitted_tags = Array(permitted_classes).map do |c| - "!ruby/object:#{c.is_a?(Module) ? c.name : c}" - end + @permitted_classes = permitted_classes.map {|c| "!ruby/object:#{c}" } @permitted_symbols = permitted_symbols @aliases = aliases @anchor_values = {} @@ -474,8 +472,8 @@ def store_anchor(name, value) end def build_mapping(node) - validate_tag!(node.tag) if node.tag check_anchor!(node) + validate_tag!(node.tag) if node.tag result = case node.tag when "!ruby/object:Gem::Version" @@ -605,12 +603,15 @@ def pairs_to_hash(node) end def validate_tag!(tag) - unless @permitted_tags.include?(tag) - if defined?(Psych::VERSION) - raise Psych::DisallowedClass.new("load", tag) - else - raise Psych::DisallowedClass, "Tried to load unspecified class: #{tag}" - end + return if @permitted_classes.include?(tag) + raise_disallowed_class!(tag) + end + + def raise_disallowed_class!(tag) + if defined?(Psych::VERSION) + raise Psych::DisallowedClass.new("load", tag) + else + raise Psych::DisallowedClass, "Tried to load unspecified class: #{tag}" end end diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb index 088e931e4788..0b9ecba5362a 100644 --- a/test/rubygems/test_gem_safe_yaml.rb +++ b/test/rubygems/test_gem_safe_yaml.rb @@ -1196,4 +1196,24 @@ def test_binary_tag_decoded_in_sequence_item_inline result = yaml_load(yaml) assert_equal ["SHA1"], result end + + def test_version_requirement_tag_always_permitted + yaml = <<~YAML + --- !ruby/object:Gem::Specification + name: escape + version: !ruby/object:Gem::Version + version: 0.0.4 + required_ruby_version: !ruby/object:Gem::Version::Requirement + requirements: + - - ">" + - !ruby/object:Gem::Version + version: 0.0.0 + version: + YAML + + result = yaml_load(yaml) + assert_kind_of Gem::Specification, result + assert_equal "escape", result.name + assert_kind_of Gem::Requirement, result.required_ruby_version + end end