summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSamuel Giddins <segiddins@segiddins.me>2023-08-17 15:38:53 -0700
committergit <svn-admin@ruby-lang.org>2023-08-20 09:05:17 +0000
commit1935433f5f6fecc786955dcf80e8f65ada6bcaeb (patch)
tree89dbdd575507c83e6c0cb6803af1d60995424be5 /lib
parentf69f775f243ba2036b1b24a2beda1ca932040982 (diff)
[rubygems/rubygems] Ensure that loading multiple gemspecs with legacy YAML class references does not warn
Before this, you would get constant redefinition warnings on Psych::DefaultKey Additionally, ensure the retries wont continue infinitely in the case of the ArgumentError not being caused by Marshal trying to load the undefined classes https://github.com/rubygems/rubygems/commit/919e8c2de4
Diffstat (limited to 'lib')
-rw-r--r--lib/rubygems/specification.rb15
1 files changed, 13 insertions, 2 deletions
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index 3f132b6f2b..005d2ab797 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -1302,10 +1302,20 @@ class Gem::Specification < Gem::BasicSpecification
Gem.load_yaml
yaml_set = false
+ retry_count = 0
array = begin
Marshal.load str
rescue ArgumentError => e
+ # Avoid an infinite retry loop when the argument error has nothing to do
+ # with the classes not being defined.
+ # 1 retry each allowed in case all 3 of
+ # - YAML
+ # - YAML::Syck::DefaultKey
+ # - YAML::Private type
+ # need to be defined
+ raise if retry_count >= 3
+
#
# Some very old marshaled specs included references to `YAML::PrivateType`
# and `YAML::Syck::DefaultKey` constants due to bugs in the old emitter
@@ -1323,11 +1333,12 @@ class Gem::Specification < Gem::BasicSpecification
if message.include?("YAML::Syck::")
YAML.const_set "Syck", YAML unless YAML.const_defined?(:Syck)
- YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey")
- elsif message.include?("YAML::PrivateType")
+ YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey") && !YAML::Syck.const_defined?(:DefaultKey)
+ elsif message.include?("YAML::PrivateType") && !YAML.const_defined?(:PrivateType)
YAML.const_set "PrivateType", Class.new
end
+ retry_count += 1
retry
ensure
Object.__send__(:remove_const, "YAML") if yaml_set