rubygems-update 3.6.1 → 3.6.3

Sign up to get free protection for your applications and to get access to all the features.
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
  ##