rubygems-update 3.6.1 → 3.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/bundler/CHANGELOG.md +32 -0
  4. data/bundler/README.md +1 -1
  5. data/bundler/lib/bundler/build_metadata.rb +2 -2
  6. data/bundler/lib/bundler/cli/outdated.rb +6 -4
  7. data/bundler/lib/bundler/definition.rb +2 -2
  8. data/bundler/lib/bundler/dependency.rb +1 -1
  9. data/bundler/lib/bundler/feature_flag.rb +2 -6
  10. data/bundler/lib/bundler/installer.rb +15 -1
  11. data/bundler/lib/bundler/man/bundle-add.1 +3 -3
  12. data/bundler/lib/bundler/man/bundle-binstubs.1 +3 -3
  13. data/bundler/lib/bundler/man/bundle-cache.1 +3 -3
  14. data/bundler/lib/bundler/man/bundle-check.1 +3 -3
  15. data/bundler/lib/bundler/man/bundle-clean.1 +3 -3
  16. data/bundler/lib/bundler/man/bundle-config.1 +3 -3
  17. data/bundler/lib/bundler/man/bundle-console.1 +3 -3
  18. data/bundler/lib/bundler/man/bundle-doctor.1 +3 -3
  19. data/bundler/lib/bundler/man/bundle-env.1 +3 -3
  20. data/bundler/lib/bundler/man/bundle-exec.1 +3 -3
  21. data/bundler/lib/bundler/man/bundle-fund.1 +3 -3
  22. data/bundler/lib/bundler/man/bundle-gem.1 +3 -3
  23. data/bundler/lib/bundler/man/bundle-help.1 +3 -3
  24. data/bundler/lib/bundler/man/bundle-info.1 +3 -3
  25. data/bundler/lib/bundler/man/bundle-init.1 +3 -3
  26. data/bundler/lib/bundler/man/bundle-inject.1 +3 -3
  27. data/bundler/lib/bundler/man/bundle-install.1 +3 -3
  28. data/bundler/lib/bundler/man/bundle-issue.1 +3 -3
  29. data/bundler/lib/bundler/man/bundle-licenses.1 +3 -3
  30. data/bundler/lib/bundler/man/bundle-list.1 +3 -3
  31. data/bundler/lib/bundler/man/bundle-lock.1 +4 -4
  32. data/bundler/lib/bundler/man/bundle-lock.1.ronn +1 -1
  33. data/bundler/lib/bundler/man/bundle-open.1 +3 -3
  34. data/bundler/lib/bundler/man/bundle-outdated.1 +3 -3
  35. data/bundler/lib/bundler/man/bundle-platform.1 +3 -3
  36. data/bundler/lib/bundler/man/bundle-plugin.1 +3 -3
  37. data/bundler/lib/bundler/man/bundle-pristine.1 +3 -3
  38. data/bundler/lib/bundler/man/bundle-remove.1 +3 -3
  39. data/bundler/lib/bundler/man/bundle-show.1 +3 -3
  40. data/bundler/lib/bundler/man/bundle-update.1 +3 -3
  41. data/bundler/lib/bundler/man/bundle-version.1 +3 -3
  42. data/bundler/lib/bundler/man/bundle-viz.1 +3 -3
  43. data/bundler/lib/bundler/man/bundle.1 +3 -3
  44. data/bundler/lib/bundler/man/gemfile.5 +3 -3
  45. data/bundler/lib/bundler/plugin/index.rb +4 -0
  46. data/bundler/lib/bundler/resolver/base.rb +2 -1
  47. data/bundler/lib/bundler/resolver/package.rb +1 -1
  48. data/bundler/lib/bundler/resolver.rb +2 -1
  49. data/bundler/lib/bundler/ruby_dsl.rb +12 -3
  50. data/bundler/lib/bundler/rubygems_integration.rb +0 -12
  51. data/bundler/lib/bundler/self_manager.rb +3 -2
  52. data/bundler/lib/bundler/source/git.rb +1 -0
  53. data/bundler/lib/bundler/spec_set.rb +16 -2
  54. data/bundler/lib/bundler/version.rb +1 -1
  55. data/bundler/lib/bundler.rb +10 -30
  56. data/doc/rubygems/POLICIES.md +1 -1
  57. data/lib/rubygems/commands/environment_command.rb +5 -0
  58. data/lib/rubygems/rdoc.rb +10 -1
  59. data/lib/rubygems/requirement.rb +4 -3
  60. data/lib/rubygems/safe_marshal/reader.rb +31 -14
  61. data/lib/rubygems/safe_marshal/visitors/to_ruby.rb +29 -16
  62. data/lib/rubygems/specification.rb +3 -11
  63. data/lib/rubygems/uninstaller.rb +0 -1
  64. data/lib/rubygems/util/licenses.rb +19 -0
  65. data/lib/rubygems/version.rb +4 -1
  66. data/lib/rubygems.rb +9 -2
  67. data/rubygems-update.gemspec +1 -1
  68. metadata +3 -4
@@ -34,6 +34,10 @@ module Bundler
34
34
  rescue GenericSystemCallError
35
35
  # no need to fail when on a read-only FS, for example
36
36
  nil
37
+ rescue ArgumentError => e
38
+ # ruby 3.4 checks writability in Dir.tmpdir
39
+ raise unless e.message&.include?("could not find a temporary directory")
40
+ nil
37
41
  end
38
42
  load_index(local_index_file) if SharedHelpers.in_bundle?
39
43
  end
@@ -5,10 +5,11 @@ require_relative "package"
5
5
  module Bundler
6
6
  class Resolver
7
7
  class Base
8
- attr_reader :packages, :requirements, :source_requirements
8
+ attr_reader :packages, :requirements, :source_requirements, :locked_specs
9
9
 
10
10
  def initialize(source_requirements, dependencies, base, platforms, options)
11
11
  @source_requirements = source_requirements
12
+ @locked_specs = options[:locked_specs]
12
13
 
13
14
  @base = base
14
15
 
@@ -18,7 +18,7 @@ module Bundler
18
18
  def initialize(name, platforms, locked_specs:, unlock:, prerelease: false, prefer_local: false, dependency: nil)
19
19
  @name = name
20
20
  @platforms = platforms
21
- @locked_version = locked_specs[name].first&.version
21
+ @locked_version = locked_specs.version_for(name)
22
22
  @unlock = unlock
23
23
  @dependency = dependency || Dependency.new(name, @locked_version)
24
24
  @top_level = !dependency.nil?
@@ -80,7 +80,8 @@ module Bundler
80
80
  def solve_versions(root:, logger:)
81
81
  solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
82
82
  result = solver.solve
83
- result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
83
+ resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
84
+ SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
84
85
  rescue PubGrub::SolveFailure => e
85
86
  incompatibility = e.incompatibility
86
87
 
@@ -42,9 +42,18 @@ module Bundler
42
42
  # Loads the file relative to the dirname of the Gemfile itself.
43
43
  def normalize_ruby_file(filename)
44
44
  file_content = Bundler.read_file(gemfile.dirname.join(filename))
45
- # match "ruby-3.2.2" or "ruby 3.2.2" capturing version string up to the first space or comment
46
- if /^ruby(-|\s+)([^\s#]+)/.match(file_content)
47
- $2
45
+ # match "ruby-3.2.2", ruby = "3.2.2" or "ruby 3.2.2" capturing version string up to the first space or comment
46
+ if /^ # Start of line
47
+ ruby # Literal "ruby"
48
+ [\s-]* # Optional whitespace or hyphens (for "ruby-3.2.2" format)
49
+ (?:=\s*)? # Optional equals sign with whitespace (for ruby = "3.2.2" format)
50
+ "? # Optional opening quote
51
+ ( # Start capturing group
52
+ [^\s#"]+ # One or more chars that aren't spaces, #, or quotes
53
+ ) # End capturing group
54
+ "? # Optional closing quote
55
+ /x.match(file_content)
56
+ $1
48
57
  else
49
58
  file_content.strip
50
59
  end
@@ -134,18 +134,6 @@ module Bundler
134
134
  loaded_gem_paths.flatten
135
135
  end
136
136
 
137
- def load_plugins
138
- Gem.load_plugins
139
- end
140
-
141
- def load_plugin_files(plugin_files)
142
- Gem.load_plugin_files(plugin_files)
143
- end
144
-
145
- def load_env_plugins
146
- Gem.load_env_plugins
147
- end
148
-
149
137
  def ui=(obj)
150
138
  Gem::DefaultUserInteraction.ui = obj
151
139
  end
@@ -84,8 +84,9 @@ module Bundler
84
84
  require "shellwords"
85
85
  cmd = [*Shellwords.shellsplit(bundler_spec_original_cmd), *ARGV]
86
86
  else
87
- cmd = [Process.argv0, *ARGV]
88
- cmd.unshift(Gem.ruby) unless File.executable?(Process.argv0)
87
+ argv0 = File.exist?($PROGRAM_NAME) ? $PROGRAM_NAME : Process.argv0
88
+ cmd = [argv0, *ARGV]
89
+ cmd.unshift(Gem.ruby) unless File.executable?(argv0)
89
90
  end
90
91
 
91
92
  Bundler.with_original_env do
@@ -282,6 +282,7 @@ module Bundler
282
282
  FileUtils.rm_rf(app_cache_path)
283
283
  git_proxy.checkout if migrate || requires_checkout?
284
284
  git_proxy.copy_to(app_cache_path, @submodules)
285
+ serialize_gemspecs_in(app_cache_path)
285
286
  end
286
287
 
287
288
  def checkout
@@ -133,8 +133,8 @@ module Bundler
133
133
  validation_set.incomplete_specs.any?
134
134
  end
135
135
 
136
- def missing_specs_for(dependencies)
137
- materialize_dependencies(dependencies)
136
+ def missing_specs_for(deps)
137
+ materialize_dependencies(deps)
138
138
 
139
139
  missing_specs
140
140
  end
@@ -163,12 +163,20 @@ module Bundler
163
163
  @specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
164
164
  end
165
165
 
166
+ def specs_with_additional_variants_from(other)
167
+ sorted | additional_variants_from(other)
168
+ end
169
+
166
170
  def delete_by_name(name)
167
171
  @specs.reject! {|spec| spec.name == name }
168
172
 
169
173
  reset!
170
174
  end
171
175
 
176
+ def version_for(name)
177
+ self[name].first&.version
178
+ end
179
+
172
180
  def what_required(spec)
173
181
  unless req = find {|s| s.runtime_dependencies.any? {|d| d.name == spec.name } }
174
182
  return [spec]
@@ -273,6 +281,12 @@ module Bundler
273
281
  @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq
274
282
  end
275
283
 
284
+ def additional_variants_from(other)
285
+ other.select do |spec|
286
+ version_for(spec.name) == spec.version && valid_dependencies?(spec)
287
+ end
288
+ end
289
+
276
290
  def valid_dependencies?(s)
277
291
  validate_deps(s) == :valid
278
292
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.6.1".freeze
4
+ VERSION = "2.6.3".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
@@ -212,7 +212,6 @@ module Bundler
212
212
  # Bundler.require(:test) # requires second_gem
213
213
  #
214
214
  def require(*groups)
215
- load_plugins
216
215
  setup(*groups).require(*groups)
217
216
  end
218
217
 
@@ -548,15 +547,7 @@ module Bundler
548
547
  def load_gemspec_uncached(file, validate = false)
549
548
  path = Pathname.new(file)
550
549
  contents = read_file(file)
551
- spec = if contents.start_with?("---") # YAML header
552
- eval_yaml_gemspec(path, contents)
553
- else
554
- # Eval the gemspec from its parent directory, because some gemspecs
555
- # depend on "./" relative paths.
556
- SharedHelpers.chdir(path.dirname.to_s) do
557
- eval_gemspec(path, contents)
558
- end
559
- end
550
+ spec = eval_gemspec(path, contents)
560
551
  return unless spec
561
552
  spec.loaded_from = path.expand_path.to_s
562
553
  Bundler.rubygems.validate(spec) if validate
@@ -576,23 +567,6 @@ module Bundler
576
567
  @feature_flag ||= FeatureFlag.new(VERSION)
577
568
  end
578
569
 
579
- def load_plugins(definition = Bundler.definition)
580
- return if defined?(@load_plugins_ran)
581
-
582
- Bundler.rubygems.load_plugins
583
-
584
- requested_path_gems = definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
585
- path_plugin_files = requested_path_gems.flat_map do |spec|
586
- spec.matches_for_glob("rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
587
- rescue TypeError
588
- error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
589
- raise Gem::InvalidSpecificationException, error_message
590
- end
591
- Bundler.rubygems.load_plugin_files(path_plugin_files)
592
- Bundler.rubygems.load_env_plugins
593
- @load_plugins_ran = true
594
- end
595
-
596
570
  def reset!
597
571
  reset_paths!
598
572
  Plugin.reset!
@@ -675,12 +649,18 @@ module Bundler
675
649
  Kernel.require "psych"
676
650
 
677
651
  Gem::Specification.from_yaml(contents)
678
- rescue ::Psych::SyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception
679
- eval_gemspec(path, contents)
680
652
  end
681
653
 
682
654
  def eval_gemspec(path, contents)
683
- eval(contents, TOPLEVEL_BINDING.dup, path.expand_path.to_s)
655
+ if contents.start_with?("---") # YAML header
656
+ eval_yaml_gemspec(path, contents)
657
+ else
658
+ # Eval the gemspec from its parent directory, because some gemspecs
659
+ # depend on "./" relative paths.
660
+ SharedHelpers.chdir(path.dirname.to_s) do
661
+ eval(contents, TOPLEVEL_BINDING.dup, path.expand_path.to_s)
662
+ end
663
+ end
684
664
  rescue ScriptError, StandardError => e
685
665
  msg = "There was an error while loading `#{path.basename}`: #{e.message}"
686
666
 
@@ -95,7 +95,7 @@ the version in all version files, synchronizes both changelogs to include all
95
95
  backported changes and commits that change on top of the cherry-picks.
96
96
 
97
97
  Note that this task requires all user facing pull requests to be tagged with
98
- specific labels. See [Merging a PR](/bundler/doc/playbooks/MERGING_A_PR.md) for details.
98
+ specific labels. See [Merging a PR](../bundler/playbooks/MERGING_A_PR.md) for details.
99
99
 
100
100
  Also note that when this task cherry-picks, it cherry-picks the merge commits
101
101
  using the following command:
@@ -15,6 +15,7 @@ class Gem::Commands::EnvironmentCommand < Gem::Command
15
15
  version display the gem format version
16
16
  remotesources display the remote gem servers
17
17
  platform display the supported gem platforms
18
+ credentials display the path where credentials are stored
18
19
  <omitted> display everything
19
20
  EOF
20
21
  args.gsub(/^\s+/, "")
@@ -88,6 +89,8 @@ lib/rubygems/defaults/operating_system.rb
88
89
  Gem.sources.to_a.join("\n")
89
90
  when /^platform/ then
90
91
  Gem.platforms.join(File::PATH_SEPARATOR)
92
+ when /^credentials/, /^creds/ then
93
+ Gem.configuration.credentials_path
91
94
  when nil then
92
95
  show_environment
93
96
  else
@@ -114,6 +117,8 @@ lib/rubygems/defaults/operating_system.rb
114
117
 
115
118
  out << " - USER INSTALLATION DIRECTORY: #{Gem.user_dir}\n"
116
119
 
120
+ out << " - CREDENTIALS FILE: #{Gem.configuration.credentials_path}\n"
121
+
117
122
  out << " - RUBYGEMS PREFIX: #{Gem.prefix}\n" unless Gem.prefix.nil?
118
123
 
119
124
  out << " - RUBY EXECUTABLE: #{Gem.ruby}\n"
data/lib/rubygems/rdoc.rb CHANGED
@@ -6,8 +6,17 @@ begin
6
6
  require "rdoc/rubygems_hook"
7
7
  module Gem
8
8
  RDoc = ::RDoc::RubygemsHook
9
+
10
+ ##
11
+ # Returns whether RDoc defines its own install hooks through a RubyGems
12
+ # plugin. This and whatever is guarded by it can be removed once no
13
+ # supported Ruby ships with RDoc older than 6.9.0.
14
+
15
+ def self.rdoc_hooks_defined_via_plugin?
16
+ Gem::Version.new(::RDoc::VERSION) >= Gem::Version.new("6.9.0")
17
+ end
9
18
  end
10
19
 
11
- Gem.done_installing(&Gem::RDoc.method(:generation_hook))
20
+ Gem.done_installing(&Gem::RDoc.method(:generation_hook)) unless Gem.rdoc_hooks_defined_via_plugin?
12
21
  rescue LoadError
13
22
  end
@@ -22,7 +22,7 @@ class Gem::Requirement
22
22
 
23
23
  SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc:
24
24
 
25
- quoted = OPS.keys.map {|k| Regexp.quote k }.join "|"
25
+ quoted = Regexp.union(OPS.keys)
26
26
  PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc:
27
27
 
28
28
  ##
@@ -201,7 +201,8 @@ class Gem::Requirement
201
201
  def marshal_load(array) # :nodoc:
202
202
  @requirements = array[0]
203
203
 
204
- raise TypeError, "wrong @requirements" unless Array === @requirements
204
+ raise TypeError, "wrong @requirements" unless Array === @requirements &&
205
+ @requirements.all? {|r| r.size == 2 && (r.first.is_a?(String) || r[0] = "=") && r.last.is_a?(Gem::Version) }
205
206
  end
206
207
 
207
208
  def yaml_initialize(tag, vals) # :nodoc:
@@ -238,7 +239,7 @@ class Gem::Requirement
238
239
  def satisfied_by?(version)
239
240
  raise ArgumentError, "Need a Gem::Version: #{version.inspect}" unless
240
241
  Gem::Version === version
241
- requirements.all? {|op, rv| OPS[op].call version, rv }
242
+ requirements.all? {|op, rv| OPS.fetch(op).call version, rv }
242
243
  end
243
244
 
244
245
  alias_method :===, :satisfied_by?
@@ -20,6 +20,12 @@ module Gem
20
20
  class EOFError < Error
21
21
  end
22
22
 
23
+ class DataTooShortError < Error
24
+ end
25
+
26
+ class NegativeLengthError < Error
27
+ end
28
+
23
29
  def initialize(io)
24
30
  @io = io
25
31
  end
@@ -27,7 +33,7 @@ module Gem
27
33
  def read!
28
34
  read_header
29
35
  root = read_element
30
- raise UnconsumedBytesError unless @io.eof?
36
+ raise UnconsumedBytesError, "expected EOF, got #{@io.read(10).inspect}... after top-level element #{root.class}" unless @io.eof?
31
37
  root
32
38
  end
33
39
 
@@ -41,8 +47,16 @@ module Gem
41
47
  raise UnsupportedVersionError, "Unsupported marshal version #{v.bytes.map(&:ord).join(".")}, expected #{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" unless v == MARSHAL_VERSION
42
48
  end
43
49
 
50
+ def read_bytes(n)
51
+ raise NegativeLengthError if n < 0
52
+ str = @io.read(n)
53
+ raise EOFError, "expected #{n} bytes, got EOF" if str.nil?
54
+ raise DataTooShortError, "expected #{n} bytes, got #{str.inspect}" unless str.bytesize == n
55
+ str
56
+ end
57
+
44
58
  def read_byte
45
- @io.getbyte
59
+ @io.getbyte || raise(EOFError, "Unexpected EOF")
46
60
  end
47
61
 
48
62
  def read_integer
@@ -67,8 +81,6 @@ module Gem
67
81
  read_byte | (read_byte << 8) | -0x10000
68
82
  when 0xFF
69
83
  read_byte | -0x100
70
- when nil
71
- raise EOFError, "Unexpected EOF"
72
84
  else
73
85
  signed = (b ^ 128) - 128
74
86
  if b >= 128
@@ -107,8 +119,6 @@ module Gem
107
119
  when 47 then read_regexp # ?/
108
120
  when 83 then read_struct # ?S
109
121
  when 67 then read_user_class # ?C
110
- when nil
111
- raise EOFError, "Unexpected EOF"
112
122
  else
113
123
  raise Error, "Unknown marshal type discriminator #{type.chr.inspect} (#{type})"
114
124
  end
@@ -127,7 +137,7 @@ module Gem
127
137
  Elements::Symbol.new(byte.chr)
128
138
  end
129
139
  else
130
- name = -@io.read(len)
140
+ name = read_bytes(len)
131
141
  Elements::Symbol.new(name)
132
142
  end
133
143
  end
@@ -138,7 +148,7 @@ module Gem
138
148
  def read_string
139
149
  length = read_integer
140
150
  return EMPTY_STRING if length == 0
141
- str = @io.read(length)
151
+ str = read_bytes(length)
142
152
  Elements::String.new(str)
143
153
  end
144
154
 
@@ -152,7 +162,7 @@ module Gem
152
162
 
153
163
  def read_user_defined
154
164
  name = read_element
155
- binary_string = @io.read(read_integer)
165
+ binary_string = read_bytes(read_integer)
156
166
  Elements::UserDefined.new(name, binary_string)
157
167
  end
158
168
 
@@ -162,6 +172,7 @@ module Gem
162
172
  def read_array
163
173
  length = read_integer
164
174
  return EMPTY_ARRAY if length == 0
175
+ raise NegativeLengthError if length < 0
165
176
  elements = Array.new(length) do
166
177
  read_element
167
178
  end
@@ -170,7 +181,9 @@ module Gem
170
181
 
171
182
  def read_object_with_ivars
172
183
  object = read_element
173
- ivars = Array.new(read_integer) do
184
+ length = read_integer
185
+ raise NegativeLengthError if length < 0
186
+ ivars = Array.new(length) do
174
187
  [read_element, read_element]
175
188
  end
176
189
  Elements::WithIvars.new(object, ivars)
@@ -239,7 +252,9 @@ module Gem
239
252
  end
240
253
 
241
254
  def read_hash_with_default_value
242
- pairs = Array.new(read_integer) do
255
+ length = read_integer
256
+ raise NegativeLengthError if length < 0
257
+ pairs = Array.new(length) do
243
258
  [read_element, read_element]
244
259
  end
245
260
  default = read_element
@@ -249,7 +264,9 @@ module Gem
249
264
  def read_object
250
265
  name = read_element
251
266
  object = Elements::Object.new(name)
252
- ivars = Array.new(read_integer) do
267
+ length = read_integer
268
+ raise NegativeLengthError if length < 0
269
+ ivars = Array.new(length) do
253
270
  [read_element, read_element]
254
271
  end
255
272
  Elements::WithIvars.new(object, ivars)
@@ -260,13 +277,13 @@ module Gem
260
277
  end
261
278
 
262
279
  def read_float
263
- string = @io.read(read_integer)
280
+ string = read_bytes(read_integer)
264
281
  Elements::Float.new(string)
265
282
  end
266
283
 
267
284
  def read_bignum
268
285
  sign = read_byte
269
- data = @io.read(read_integer * 2)
286
+ data = read_bytes(read_integer * 2)
270
287
  Elements::Bignum.new(sign, data)
271
288
  end
272
289
 
@@ -45,7 +45,7 @@ module Gem::SafeMarshal
45
45
  idx = 0
46
46
  # not idiomatic, but there's a huge number of IMEMOs allocated here, so we avoid the block
47
47
  # because this is such a hot path when doing a bundle install with the full index
48
- until idx == size
48
+ while idx < size
49
49
  push_stack idx
50
50
  array << visit(elements[idx])
51
51
  idx += 1
@@ -98,16 +98,21 @@ module Gem::SafeMarshal
98
98
  end
99
99
 
100
100
  s = e.object.binary_string
101
+ # 122 is the largest integer that can be represented in marshal in a single byte
102
+ raise TimeTooLargeError.new("binary string too large", stack: formatted_stack) if s.bytesize > 122
101
103
 
102
104
  marshal_string = "\x04\bIu:\tTime".b
103
- marshal_string.concat(s.size + 5)
105
+ marshal_string.concat(s.bytesize + 5)
104
106
  marshal_string << s
107
+ # internal is limited to 5, so no overflow is possible
105
108
  marshal_string.concat(internal.size + 5)
106
109
 
107
110
  internal.each do |k, v|
111
+ k = k.name
112
+ # ivar name can't be too large because only known ivars are in the internal ivars list
108
113
  marshal_string.concat(":")
109
- marshal_string.concat(k.size + 5)
110
- marshal_string.concat(k.to_s)
114
+ marshal_string.concat(k.bytesize + 5)
115
+ marshal_string.concat(k)
111
116
  dumped = Marshal.dump(v)
112
117
  dumped[0, 2] = ""
113
118
  marshal_string.concat(dumped)
@@ -171,11 +176,11 @@ module Gem::SafeMarshal
171
176
  end
172
177
 
173
178
  def visit_Gem_SafeMarshal_Elements_ObjectLink(o)
174
- @objects[o.offset]
179
+ @objects.fetch(o.offset)
175
180
  end
176
181
 
177
182
  def visit_Gem_SafeMarshal_Elements_SymbolLink(o)
178
- @symbols[o.offset]
183
+ @symbols.fetch(o.offset)
179
184
  end
180
185
 
181
186
  def visit_Gem_SafeMarshal_Elements_UserDefined(o)
@@ -219,16 +224,18 @@ module Gem::SafeMarshal
219
224
  end
220
225
 
221
226
  def visit_Gem_SafeMarshal_Elements_Float(f)
222
- case f.string
223
- when "inf"
224
- ::Float::INFINITY
225
- when "-inf"
226
- -::Float::INFINITY
227
- when "nan"
228
- ::Float::NAN
229
- else
230
- f.string.to_f
231
- end
227
+ register_object(
228
+ case f.string
229
+ when "inf"
230
+ ::Float::INFINITY
231
+ when "-inf"
232
+ -::Float::INFINITY
233
+ when "nan"
234
+ ::Float::NAN
235
+ else
236
+ f.string.to_f
237
+ end
238
+ )
232
239
  end
233
240
 
234
241
  def visit_Gem_SafeMarshal_Elements_Bignum(b)
@@ -374,6 +381,12 @@ module Gem::SafeMarshal
374
381
  class Error < StandardError
375
382
  end
376
383
 
384
+ class TimeTooLargeError < Error
385
+ def initialize(message, stack:)
386
+ super "#{message} @ #{stack.join "."}"
387
+ end
388
+ end
389
+
377
390
  class UnpermittedSymbolError < Error
378
391
  def initialize(symbol:, stack:)
379
392
  @symbol = symbol
@@ -1322,7 +1322,7 @@ class Gem::Specification < Gem::BasicSpecification
1322
1322
  spec.instance_variable_set :@description, array[13]
1323
1323
  spec.instance_variable_set :@homepage, array[14]
1324
1324
  spec.instance_variable_set :@has_rdoc, array[15]
1325
- spec.instance_variable_set :@licenses, [array[17]]
1325
+ spec.instance_variable_set :@licenses, array[17]
1326
1326
  spec.instance_variable_set :@metadata, array[18]
1327
1327
  spec.instance_variable_set :@loaded, false
1328
1328
  spec.instance_variable_set :@activated, false
@@ -1817,16 +1817,8 @@ class Gem::Specification < Gem::BasicSpecification
1817
1817
  def encode_with(coder) # :nodoc:
1818
1818
  coder.add "name", @name
1819
1819
  coder.add "version", @version
1820
- platform = case @new_platform
1821
- when nil, "" then
1822
- "ruby"
1823
- when String then
1824
- @new_platform
1825
- else
1826
- @new_platform.to_s
1827
- end
1828
- coder.add "platform", platform
1829
- coder.add "original_platform", @original_platform.to_s if platform != @original_platform.to_s
1820
+ coder.add "platform", platform.to_s
1821
+ coder.add "original_platform", original_platform.to_s if platform.to_s != original_platform.to_s
1830
1822
 
1831
1823
  attributes = @@attributes.map(&:to_s) - %w[name version platform]
1832
1824
  attributes.each do |name|
@@ -10,7 +10,6 @@ require "fileutils"
10
10
  require_relative "../rubygems"
11
11
  require_relative "installer_uninstaller_utils"
12
12
  require_relative "dependency_list"
13
- require_relative "rdoc"
14
13
  require_relative "user_interaction"
15
14
 
16
15
  ##