rubygems-update 3.0.0 → 3.0.9

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.travis.yml +2 -0
  4. data/CODE_OF_CONDUCT.md +10 -8
  5. data/CONTRIBUTING.md +7 -0
  6. data/History.txt +180 -0
  7. data/Manifest.txt +5 -3
  8. data/README.md +6 -0
  9. data/Rakefile +33 -7
  10. data/bundler/CHANGELOG.md +11 -0
  11. data/bundler/lib/bundler/build_metadata.rb +2 -2
  12. data/bundler/lib/bundler/rubygems_gem_installer.rb +7 -0
  13. data/bundler/lib/bundler/source/metadata.rb +2 -3
  14. data/bundler/lib/bundler/version.rb +1 -1
  15. data/bundler/man/bundle.ronn +3 -0
  16. data/lib/rubygems/command_manager.rb +12 -4
  17. data/lib/rubygems/commands/build_command.rb +28 -13
  18. data/lib/rubygems/commands/owner_command.rb +6 -1
  19. data/lib/rubygems/commands/push_command.rb +2 -0
  20. data/lib/rubygems/commands/setup_command.rb +14 -16
  21. data/lib/rubygems/commands/uninstall_command.rb +16 -6
  22. data/lib/rubygems/commands/which_command.rb +1 -3
  23. data/lib/rubygems/defaults.rb +1 -8
  24. data/lib/rubygems/dependency.rb +1 -1
  25. data/lib/rubygems/dependency_installer.rb +1 -2
  26. data/lib/rubygems/dependency_list.rb +1 -1
  27. data/lib/rubygems/exceptions.rb +0 -4
  28. data/lib/rubygems/gemcutter_utilities.rb +14 -7
  29. data/lib/rubygems/install_update_options.rb +1 -1
  30. data/lib/rubygems/installer.rb +37 -15
  31. data/lib/rubygems/installer_test_case.rb +2 -2
  32. data/lib/rubygems/package/old.rb +1 -1
  33. data/lib/rubygems/package/tar_header.rb +11 -2
  34. data/lib/rubygems/package.rb +12 -2
  35. data/lib/rubygems/rdoc.rb +2 -2
  36. data/lib/rubygems/remote_fetcher.rb +15 -54
  37. data/lib/rubygems/request.rb +1 -1
  38. data/lib/rubygems/request_set/gem_dependency_api.rb +11 -10
  39. data/lib/rubygems/requirement.rb +16 -5
  40. data/lib/rubygems/resolver.rb +4 -1
  41. data/lib/rubygems/s3_uri_signer.rb +183 -0
  42. data/lib/rubygems/security_option.rb +0 -1
  43. data/lib/rubygems/specification.rb +21 -23
  44. data/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem +21 -0
  45. data/lib/rubygems/stub_specification.rb +1 -2
  46. data/lib/rubygems/test_case.rb +23 -12
  47. data/lib/rubygems/uninstaller.rb +1 -1
  48. data/lib/rubygems/user_interaction.rb +4 -1
  49. data/lib/rubygems/util.rb +13 -1
  50. data/lib/rubygems.rb +8 -13
  51. data/rubygems-update.gemspec +1 -1
  52. data/test/rubygems/ca_cert.pem +74 -65
  53. data/test/rubygems/client.pem +103 -45
  54. data/test/rubygems/ssl_cert.pem +78 -17
  55. data/test/rubygems/ssl_key.pem +25 -13
  56. data/test/rubygems/test_bundled_ca.rb +8 -5
  57. data/test/rubygems/test_gem.rb +55 -13
  58. data/test/rubygems/test_gem_bundler_version_finder.rb +4 -0
  59. data/test/rubygems/test_gem_command_manager.rb +10 -0
  60. data/test/rubygems/test_gem_commands_build_command.rb +1 -0
  61. data/test/rubygems/test_gem_commands_push_command.rb +15 -0
  62. data/test/rubygems/test_gem_commands_setup_command.rb +11 -7
  63. data/test/rubygems/test_gem_commands_uninstall_command.rb +80 -1
  64. data/test/rubygems/test_gem_ext_cmake_builder.rb +1 -1
  65. data/test/rubygems/test_gem_indexer.rb +15 -8
  66. data/test/rubygems/test_gem_installer.rb +191 -22
  67. data/test/rubygems/test_gem_package.rb +37 -0
  68. data/test/rubygems/test_gem_package_tar_header.rb +41 -0
  69. data/test/rubygems/test_gem_package_tar_writer.rb +3 -0
  70. data/test/rubygems/test_gem_rdoc.rb +1 -135
  71. data/test/rubygems/test_gem_remote_fetcher.rb +133 -14
  72. data/test/rubygems/test_gem_request.rb +4 -4
  73. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +80 -57
  74. data/test/rubygems/test_gem_requirement.rb +6 -0
  75. data/test/rubygems/test_gem_security_policy.rb +1 -1
  76. data/test/rubygems/test_gem_specification.rb +32 -0
  77. data/test/rubygems/test_gem_stream_ui.rb +2 -2
  78. data/test/rubygems/test_gem_text.rb +5 -0
  79. data/test/rubygems/test_gem_uninstaller.rb +21 -2
  80. data/test/rubygems/test_gem_util.rb +25 -0
  81. data/util/ci +6 -1
  82. data/util/cops/deprecations.rb +52 -0
  83. data/util/create_certs.sh +27 -0
  84. data/util/create_encrypted_key.rb +4 -4
  85. data/util/update_bundled_ca_certificates.rb +1 -3
  86. metadata +12 -10
  87. data/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem +0 -23
  88. data/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem +0 -25
  89. /data/lib/rubygems/ssl_certs/{index.rubygems.org → rubygems.org}/GlobalSignRootCA.pem +0 -0
@@ -207,6 +207,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
207
207
  gs.write @gem.to_ruby
208
208
  end
209
209
 
210
+ @cmd.options[:build_path] = gemspec_dir
210
211
  @cmd.options[:args] = [gemspec_file]
211
212
 
212
213
  use_ui @ui do
@@ -199,6 +199,21 @@ class TestGemCommandsPushCommand < Gem::TestCase
199
199
  send_battery
200
200
  end
201
201
 
202
+ def test_sending_gem_with_env_var_api_key
203
+ @host = "http://privategemserver.example"
204
+
205
+ @spec, @path = util_gem "freebird", "1.0.1" do |spec|
206
+ spec.metadata['allowed_push_host'] = @host
207
+ end
208
+
209
+ @api_key = "PRIVKEY"
210
+ ENV["GEM_HOST_API_KEY"] = "PRIVKEY"
211
+
212
+ @response = "Successfully registered gem: freebird (1.0.1)"
213
+ @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
214
+ send_battery
215
+ end
216
+
202
217
  def test_sending_gem_to_allowed_push_host_with_basic_credentials
203
218
  @sanitized_host = "http://privategemserver.example"
204
219
  @host = "http://user:password@privategemserver.example"
@@ -38,6 +38,7 @@ class TestGemCommandsSetupCommand < Gem::TestCase
38
38
  FileUtils.mkdir_p 'default/gems'
39
39
 
40
40
  gemspec = Gem::Specification.new
41
+ gemspec.author = "Us"
41
42
  gemspec.name = "bundler"
42
43
  gemspec.version = BUNDLER_VERS
43
44
  gemspec.bindir = "exe"
@@ -166,16 +167,19 @@ class TestGemCommandsSetupCommand < Gem::TestCase
166
167
  def test_install_default_bundler_gem
167
168
  @cmd.extend FileUtils
168
169
 
169
- @cmd.install_default_bundler_gem
170
+ bin_dir = File.join(@gemhome, 'bin')
171
+ @cmd.install_default_bundler_gem bin_dir
170
172
 
171
- if Gem.win_platform?
172
- bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
173
- default_spec_path = File.join(Gem::Specification.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
174
- spec = Gem::Specification.load(default_spec_path)
173
+ bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
174
+ default_spec_path = File.join(Gem::Specification.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
175
+ spec = Gem::Specification.load(default_spec_path)
175
176
 
176
- spec.executables.each do |e|
177
- assert_path_exists File.join(spec.bin_dir, "#{e}.bat")
177
+ spec.executables.each do |e|
178
+ if Gem.win_platform?
179
+ assert_path_exists File.join(bin_dir, "#{e}.bat")
178
180
  end
181
+
182
+ assert_path_exists File.join bin_dir, e
179
183
  end
180
184
 
181
185
  default_dir = Gem::Specification.default_specifications_dir
@@ -192,6 +192,62 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
192
192
  assert File.exist? File.join(@gemhome, 'bin', 'executable')
193
193
  end
194
194
 
195
+ def test_uninstall_selection
196
+ ui = Gem::MockGemUi.new "1\n"
197
+
198
+ util_make_gems
199
+
200
+ list = Gem::Specification.find_all_by_name 'a'
201
+
202
+ @cmd.options[:args] = ['a']
203
+
204
+ use_ui ui do
205
+ @cmd.execute
206
+ end
207
+
208
+ updated_list = Gem::Specification.find_all_by_name('a')
209
+ assert_equal list.length - 1, updated_list.length
210
+
211
+ assert_match ' 1. a-1', ui.output
212
+ assert_match ' 2. a-2', ui.output
213
+ assert_match ' 3. a-3.a', ui.output
214
+ assert_match ' 4. All versions', ui.output
215
+ assert_match 'uninstalled a-1', ui.output
216
+ end
217
+
218
+ def test_uninstall_selection_multiple_gems
219
+ ui = Gem::MockGemUi.new "1\n"
220
+
221
+ util_make_gems
222
+
223
+ a_list = Gem::Specification.find_all_by_name('a')
224
+ b_list = Gem::Specification.find_all_by_name('b')
225
+ list = a_list + b_list
226
+
227
+ @cmd.options[:args] = ['a', 'b']
228
+
229
+ use_ui ui do
230
+ @cmd.execute
231
+ end
232
+
233
+ updated_a_list = Gem::Specification.find_all_by_name('a')
234
+ updated_b_list = Gem::Specification.find_all_by_name('b')
235
+ updated_list = updated_a_list + updated_b_list
236
+
237
+ assert_equal list.length - 2, updated_list.length
238
+
239
+ out = ui.output.split("\n")
240
+ assert_match 'uninstalled b-2', out.shift
241
+ assert_match '', out.shift
242
+ assert_match 'Select gem to uninstall:', out.shift
243
+ assert_match ' 1. a-1', out.shift
244
+ assert_match ' 2. a-2', out.shift
245
+ assert_match ' 3. a-3.a', out.shift
246
+ assert_match ' 4. All versions', out.shift
247
+ assert_match 'uninstalled a-1', out.shift
248
+ assert_empty out
249
+ end
250
+
195
251
  def test_execute_with_force_and_without_version_uninstalls_everything
196
252
  ui = Gem::MockGemUi.new "y\n"
197
253
 
@@ -246,7 +302,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
246
302
  gemhome2 = "#{@gemhome}2"
247
303
 
248
304
  a_4, = util_gem 'a', 4
249
- install_gem a_4, :install_dir => gemhome2
305
+ install_gem a_4
250
306
 
251
307
  Gem::Specification.dirs = [@gemhome, gemhome2]
252
308
 
@@ -264,6 +320,29 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
264
320
  assert_equal %w[default-1], Gem::Specification.all_names.sort
265
321
  end
266
322
 
323
+ def test_execute_outside_gem_home
324
+ ui = Gem::MockGemUi.new "y\n"
325
+
326
+ gemhome2 = "#{@gemhome}2"
327
+
328
+ a_4, = util_gem 'a', 4
329
+ install_gem a_4 , :install_dir => gemhome2
330
+
331
+ Gem::Specification.dirs = [@gemhome, gemhome2]
332
+
333
+ assert_includes Gem::Specification.all_names, 'a-4'
334
+
335
+ @cmd.options[:args] = ['a:4']
336
+
337
+ e = assert_raises Gem::InstallError do
338
+ use_ui ui do
339
+ @cmd.execute
340
+ end
341
+ end
342
+
343
+ assert_includes e.message, "a is not installed in GEM_HOME"
344
+ end
345
+
267
346
  def test_handle_options
268
347
  @cmd.handle_options %w[]
269
348
 
@@ -25,7 +25,7 @@ class TestGemExtCmakeBuilder < Gem::TestCase
25
25
  File.open File.join(@ext, 'CMakeLists.txt'), 'w' do |cmakelists|
26
26
  cmakelists.write <<-eo_cmake
27
27
  cmake_minimum_required(VERSION 2.6)
28
- project(self_build LANGUAGES NONE)
28
+ project(self_build NONE)
29
29
  install (FILES test.txt DESTINATION bin)
30
30
  eo_cmake
31
31
  end
@@ -37,6 +37,13 @@ class TestGemIndexer < Gem::TestCase
37
37
  @indexer = Gem::Indexer.new(@tempdir)
38
38
  end
39
39
 
40
+ def teardown
41
+ super
42
+
43
+ util_clear_gems
44
+ util_clear_default_gems
45
+ end
46
+
40
47
  def test_initialize
41
48
  assert_equal @tempdir, @indexer.dest_directory
42
49
  assert_match %r{#{Dir.mktmpdir('gem_generate_index').match(/.*-/)}}, @indexer.directory
@@ -96,8 +103,8 @@ class TestGemIndexer < Gem::TestCase
96
103
  quickdir = File.join @tempdir, 'quick'
97
104
  marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
98
105
 
99
- assert File.directory?(quickdir)
100
- assert File.directory?(marshal_quickdir)
106
+ assert_directory_exists quickdir
107
+ assert_directory_exists marshal_quickdir
101
108
 
102
109
  assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
103
110
  assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
@@ -126,8 +133,8 @@ class TestGemIndexer < Gem::TestCase
126
133
  quickdir = File.join @tempdir, 'quick'
127
134
  marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
128
135
 
129
- assert File.directory?(quickdir), 'quickdir should be directory'
130
- assert File.directory?(marshal_quickdir)
136
+ assert_directory_exists quickdir, 'quickdir should be directory'
137
+ assert_directory_exists marshal_quickdir
131
138
 
132
139
  refute_indexed quickdir, "index"
133
140
  refute_indexed quickdir, "index.rz"
@@ -172,8 +179,8 @@ class TestGemIndexer < Gem::TestCase
172
179
  quickdir = File.join @tempdir, 'quick'
173
180
  marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
174
181
 
175
- assert File.directory?(quickdir)
176
- assert File.directory?(marshal_quickdir)
182
+ assert_directory_exists quickdir
183
+ assert_directory_exists marshal_quickdir
177
184
 
178
185
  assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
179
186
  assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
@@ -308,8 +315,8 @@ class TestGemIndexer < Gem::TestCase
308
315
  quickdir = File.join @tempdir, 'quick'
309
316
  marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
310
317
 
311
- assert File.directory?(quickdir)
312
- assert File.directory?(marshal_quickdir)
318
+ assert_directory_exists quickdir
319
+ assert_directory_exists marshal_quickdir
313
320
 
314
321
  @d2_1 = util_spec 'd', '2.1'
315
322
  util_build_gem @d2_1
@@ -163,6 +163,8 @@ gem 'other', version
163
163
 
164
164
  wrapper = File.read installed_exec
165
165
  assert_match %r|generated by RubyGems|, wrapper
166
+ ensure
167
+ Gem::Installer.exec_format = nil
166
168
  end
167
169
 
168
170
  def test_check_executable_overwrite_other_gem
@@ -311,7 +313,7 @@ gem 'other', version
311
313
  @installer.wrappers = true
312
314
 
313
315
  @spec.executables = %w[executable]
314
- @spec.bindir = '.'
316
+ @spec.bindir = 'bin'
315
317
 
316
318
  exec_file = @installer.formatted_program_filename 'executable'
317
319
  exec_path = File.join @spec.gem_dir, exec_file
@@ -323,7 +325,7 @@ gem 'other', version
323
325
 
324
326
  @installer.generate_bin
325
327
 
326
- assert_equal true, File.directory?(util_inst_bindir)
328
+ assert_directory_exists (util_inst_bindir)
327
329
  installed_exec = File.join(util_inst_bindir, 'executable')
328
330
  assert_path_exists installed_exec
329
331
  assert_equal mask, File.stat(installed_exec).mode unless win_platform?
@@ -364,7 +366,7 @@ gem 'other', version
364
366
  @installer.gem_dir = @spec.gem_dir
365
367
 
366
368
  @installer.generate_bin
367
- assert File.directory? util_inst_bindir
369
+ assert_directory_exists util_inst_bindir
368
370
  installed_exec = File.join util_inst_bindir, 'executable'
369
371
  assert_path_exists installed_exec
370
372
  assert_equal mask, File.stat(installed_exec).mode unless win_platform?
@@ -381,7 +383,7 @@ gem 'other', version
381
383
 
382
384
  Gem::Installer.exec_format = 'foo-%s-bar'
383
385
  @installer.generate_bin
384
- assert_equal true, File.directory?(util_inst_bindir)
386
+ assert_directory_exists util_inst_bindir
385
387
  installed_exec = File.join util_inst_bindir, 'foo-executable-bar'
386
388
  assert_path_exists installed_exec
387
389
  ensure
@@ -395,7 +397,7 @@ gem 'other', version
395
397
 
396
398
  Gem::Installer.exec_format = 'foo-%s-bar'
397
399
  @installer.generate_bin
398
- assert_equal true, File.directory?(util_inst_bindir)
400
+ assert_directory_exists util_inst_bindir
399
401
  installed_exec = File.join util_inst_bindir, 'executable'
400
402
  assert_path_exists installed_exec
401
403
  ensure
@@ -494,7 +496,7 @@ gem 'other', version
494
496
  end
495
497
 
496
498
  @installer.generate_bin
497
- assert_equal true, File.directory?(util_inst_bindir)
499
+ assert_directory_exists util_inst_bindir
498
500
  assert_path_exists installed_exec
499
501
  assert_equal mask, File.stat(installed_exec).mode unless win_platform?
500
502
 
@@ -512,7 +514,7 @@ gem 'other', version
512
514
  @installer.gem_dir = @spec.gem_dir
513
515
 
514
516
  @installer.generate_bin
515
- assert_equal true, File.directory?(util_inst_bindir)
517
+ assert_directory_exists util_inst_bindir
516
518
  installed_exec = File.join util_inst_bindir, 'executable'
517
519
  assert_equal true, File.symlink?(installed_exec)
518
520
  assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
@@ -664,7 +666,7 @@ gem 'other', version
664
666
  @installer.generate_bin
665
667
  end
666
668
 
667
- assert_equal true, File.directory?(util_inst_bindir)
669
+ assert_directory_exists util_inst_bindir
668
670
  installed_exec = File.join(util_inst_bindir, 'executable')
669
671
  assert_path_exists installed_exec
670
672
 
@@ -740,13 +742,13 @@ gem 'other', version
740
742
  rakefile = File.join gemdir, 'ext', 'a', 'Rakefile'
741
743
  spec_file = File.join @gemhome, 'specifications', @spec.spec_name
742
744
 
743
- Gem.pre_install do |installer|
745
+ Gem.pre_install do
744
746
  refute_path_exists cache_file, 'cache file must not exist yet'
745
747
  refute_path_exists spec_file, 'spec file must not exist yet'
746
748
  true
747
749
  end
748
750
 
749
- Gem.post_build do |installer|
751
+ Gem.post_build do
750
752
  assert_path_exists gemdir, 'gem install dir must exist'
751
753
  assert_path_exists rakefile, 'gem executable must exist'
752
754
  refute_path_exists stub_exe, 'gem executable must not exist'
@@ -754,7 +756,7 @@ gem 'other', version
754
756
  true
755
757
  end
756
758
 
757
- Gem.post_install do |installer|
759
+ Gem.post_install do
758
760
  assert_path_exists cache_file, 'cache file must exist'
759
761
  assert_path_exists spec_file, 'spec file must exist'
760
762
  end
@@ -975,16 +977,16 @@ gem 'other', version
975
977
 
976
978
  def test_install_missing_dirs
977
979
  FileUtils.rm_f File.join(Gem.dir, 'cache')
978
- FileUtils.rm_f File.join(Gem.dir, 'docs')
980
+ FileUtils.rm_f File.join(Gem.dir, 'doc')
979
981
  FileUtils.rm_f File.join(Gem.dir, 'specifications')
980
982
 
981
983
  use_ui @ui do
982
984
  @installer.install
983
985
  end
984
986
 
985
- File.directory? File.join(Gem.dir, 'cache')
986
- File.directory? File.join(Gem.dir, 'docs')
987
- File.directory? File.join(Gem.dir, 'specifications')
987
+ assert_directory_exists File.join(Gem.dir, 'cache')
988
+ assert_directory_exists File.join(Gem.dir, 'doc')
989
+ assert_directory_exists File.join(Gem.dir, 'specifications')
988
990
 
989
991
  assert_path_exists File.join @gemhome, 'cache', @spec.file_name
990
992
  assert_path_exists File.join @gemhome, 'specifications', @spec.spec_name
@@ -1446,6 +1448,114 @@ gem 'other', version
1446
1448
  end
1447
1449
  end
1448
1450
 
1451
+ def test_pre_install_checks_malicious_name_before_eval
1452
+ spec = util_spec "malicious\n::Object.const_set(:FROM_EVAL, true)#", '1'
1453
+ def spec.full_name # so the spec is buildable
1454
+ "malicious-1"
1455
+ end
1456
+ def spec.validate(*args); end
1457
+
1458
+ util_build_gem spec
1459
+
1460
+ gem = File.join(@gemhome, 'cache', spec.file_name)
1461
+
1462
+ use_ui @ui do
1463
+ @installer = Gem::Installer.at gem
1464
+ e = assert_raises Gem::InstallError do
1465
+ @installer.pre_install_checks
1466
+ end
1467
+ assert_equal "#<Gem::Specification name=malicious\n::Object.const_set(:FROM_EVAL, true)# version=1> has an invalid name", e.message
1468
+ end
1469
+ refute defined?(::Object::FROM_EVAL)
1470
+ end
1471
+
1472
+ def test_pre_install_checks_malicious_require_paths_before_eval
1473
+ spec = util_spec "malicious", '1'
1474
+ def spec.full_name # so the spec is buildable
1475
+ "malicious-1"
1476
+ end
1477
+ def spec.validate(*args); end
1478
+ spec.require_paths = ["malicious\n``"]
1479
+
1480
+ util_build_gem spec
1481
+
1482
+ gem = File.join(@gemhome, 'cache', spec.file_name)
1483
+
1484
+ use_ui @ui do
1485
+ @installer = Gem::Installer.at gem
1486
+ e = assert_raises Gem::InstallError do
1487
+ @installer.pre_install_checks
1488
+ end
1489
+ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid require_paths", e.message
1490
+ end
1491
+ end
1492
+
1493
+ def test_pre_install_checks_malicious_extensions_before_eval
1494
+ skip "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform?
1495
+
1496
+ spec = util_spec "malicious", '1'
1497
+ def spec.full_name # so the spec is buildable
1498
+ "malicious-1"
1499
+ end
1500
+ def spec.validate(*args); end
1501
+ spec.extensions = ["malicious\n``"]
1502
+
1503
+ util_build_gem spec
1504
+
1505
+ gem = File.join(@gemhome, 'cache', spec.file_name)
1506
+
1507
+ use_ui @ui do
1508
+ @installer = Gem::Installer.at gem
1509
+ e = assert_raises Gem::InstallError do
1510
+ @installer.pre_install_checks
1511
+ end
1512
+ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid extensions", e.message
1513
+ end
1514
+ end
1515
+
1516
+ def test_pre_install_checks_malicious_specification_version_before_eval
1517
+ spec = util_spec "malicious", '1'
1518
+ def spec.full_name # so the spec is buildable
1519
+ "malicious-1"
1520
+ end
1521
+ def spec.validate(*args); end
1522
+ spec.specification_version = "malicious\n``"
1523
+
1524
+ util_build_gem spec
1525
+
1526
+ gem = File.join(@gemhome, 'cache', spec.file_name)
1527
+
1528
+ use_ui @ui do
1529
+ @installer = Gem::Installer.at gem
1530
+ e = assert_raises Gem::InstallError do
1531
+ @installer.pre_install_checks
1532
+ end
1533
+ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid specification_version", e.message
1534
+ end
1535
+ end
1536
+
1537
+ def test_pre_install_checks_malicious_dependencies_before_eval
1538
+ spec = util_spec "malicious", '1'
1539
+ def spec.full_name # so the spec is buildable
1540
+ "malicious-1"
1541
+ end
1542
+ def spec.validate(*args); end
1543
+ spec.add_dependency "b\nfoo", '> 5'
1544
+
1545
+ util_build_gem spec
1546
+
1547
+ gem = File.join(@gemhome, 'cache', spec.file_name)
1548
+
1549
+ use_ui @ui do
1550
+ @installer = Gem::Installer.at gem
1551
+ @installer.ignore_dependencies = true
1552
+ e = assert_raises Gem::InstallError do
1553
+ @installer.pre_install_checks
1554
+ end
1555
+ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid dependencies", e.message
1556
+ end
1557
+ end
1558
+
1449
1559
  def test_shebang
1450
1560
  util_make_exec @spec, "#!/usr/bin/ruby"
1451
1561
 
@@ -1712,28 +1822,87 @@ gem 'other', version
1712
1822
  assert_predicate spec, :default_gem?
1713
1823
  end
1714
1824
 
1715
- def test_default_gem
1825
+ def test_default_gem_without_wrappers
1716
1826
  FileUtils.rm_f File.join(Gem.dir, 'specifications')
1717
1827
 
1718
- @installer.wrappers = true
1828
+ @installer.wrappers = false
1719
1829
  @installer.options[:install_as_default] = true
1720
1830
  @installer.gem_dir = @spec.gem_dir
1721
- @installer.generate_bin
1722
1831
 
1723
1832
  use_ui @ui do
1724
1833
  @installer.install
1725
1834
  end
1726
1835
 
1727
- assert File.directory? util_inst_bindir
1728
- installed_exec = File.join util_inst_bindir, 'executable'
1836
+ assert_directory_exists File.join(@spec.gem_dir, 'bin')
1837
+ installed_exec = File.join @spec.gem_dir, 'bin', 'executable'
1729
1838
  assert_path_exists installed_exec
1730
1839
 
1731
- assert File.directory? File.join(Gem.default_dir, 'specifications')
1732
- assert File.directory? File.join(Gem.default_dir, 'specifications', 'default')
1840
+ assert_directory_exists File.join(Gem.default_dir, 'specifications')
1841
+ assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default')
1733
1842
 
1734
1843
  default_spec = eval File.read File.join(Gem.default_dir, 'specifications', 'default', 'a-2.gemspec')
1735
1844
  assert_equal Gem::Version.new("2"), default_spec.version
1736
1845
  assert_equal ['bin/executable'], default_spec.files
1846
+
1847
+ assert_directory_exists util_inst_bindir
1848
+
1849
+ installed_exec = File.join util_inst_bindir, 'executable'
1850
+ assert_path_exists installed_exec
1851
+
1852
+ wrapper = File.read installed_exec
1853
+ refute_match %r|generated by RubyGems|, wrapper
1854
+ end
1855
+
1856
+ def test_default_gem_with_wrappers
1857
+ FileUtils.rm_f File.join(Gem.dir, 'specifications')
1858
+
1859
+ @installer.wrappers = true
1860
+ @installer.options[:install_as_default] = true
1861
+ @installer.gem_dir = @spec.gem_dir
1862
+
1863
+ use_ui @ui do
1864
+ @installer.install
1865
+ end
1866
+
1867
+ assert_directory_exists util_inst_bindir
1868
+
1869
+ installed_exec = File.join util_inst_bindir, 'executable'
1870
+ assert_path_exists installed_exec
1871
+
1872
+ wrapper = File.read installed_exec
1873
+ assert_match %r|generated by RubyGems|, wrapper
1874
+ end
1875
+
1876
+ def test_default_gem_with_exe_as_bindir
1877
+ FileUtils.rm_f File.join(Gem.dir, 'specifications')
1878
+
1879
+ @spec = quick_gem 'c' do |spec|
1880
+ util_make_exec spec, '#!/usr/bin/ruby', 'exe'
1881
+ end
1882
+
1883
+ util_build_gem @spec
1884
+
1885
+ @spec.cache_file
1886
+
1887
+ installer = util_installer @spec, @gemhome
1888
+
1889
+ installer.options[:install_as_default] = true
1890
+ installer.gem_dir = @spec.gem_dir
1891
+
1892
+ use_ui @ui do
1893
+ installer.install
1894
+ end
1895
+
1896
+ assert_directory_exists File.join(@spec.gem_dir, 'exe')
1897
+ installed_exec = File.join @spec.gem_dir, 'exe', 'executable'
1898
+ assert_path_exists installed_exec
1899
+
1900
+ assert_directory_exists File.join(Gem.default_dir, 'specifications')
1901
+ assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default')
1902
+
1903
+ default_spec = eval File.read File.join(Gem.default_dir, 'specifications', 'default', 'c-2.gemspec')
1904
+ assert_equal Gem::Version.new("2"), default_spec.version
1905
+ assert_equal ['exe/executable'], default_spec.files
1737
1906
  end
1738
1907
 
1739
1908
  def old_ruby_required(requirement)
@@ -105,6 +105,7 @@ class TestGemPackage < Gem::Package::TarTestCase
105
105
  end
106
106
 
107
107
  def test_build_time_source_date_epoch
108
+ epoch = ENV["SOURCE_DATE_EPOCH"]
108
109
  ENV["SOURCE_DATE_EPOCH"] = "123456789"
109
110
 
110
111
  spec = Gem::Specification.new 'build', '1'
@@ -118,6 +119,8 @@ class TestGemPackage < Gem::Package::TarTestCase
118
119
  package = Gem::Package.new spec.file_name
119
120
 
120
121
  assert_equal Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, package.build_time
122
+ ensure
123
+ ENV["SOURCE_DATE_EPOCH"] = epoch
121
124
  end
122
125
 
123
126
  def test_add_files
@@ -526,6 +529,40 @@ class TestGemPackage < Gem::Package::TarTestCase
526
529
  end
527
530
  end
528
531
 
532
+ def test_extract_symlink_parent_doesnt_delete_user_dir
533
+ package = Gem::Package.new @gem
534
+
535
+ # Extract into a subdirectory of @destination; if this test fails it writes
536
+ # a file outside destination_subdir, but we want the file to remain inside
537
+ # @destination so it will be cleaned up.
538
+ destination_subdir = File.join @destination, 'subdir'
539
+ FileUtils.mkdir_p destination_subdir
540
+
541
+ destination_user_dir = File.join @destination, 'user'
542
+ destination_user_subdir = File.join destination_user_dir, 'dir'
543
+ FileUtils.mkdir_p destination_user_subdir
544
+
545
+ tgz_io = util_tar_gz do |tar|
546
+ tar.add_symlink 'link', destination_user_dir, 16877
547
+ tar.add_symlink 'link/dir', '.', 16877
548
+ end
549
+
550
+ e = assert_raises(Gem::Package::PathError, Errno::EACCES) do
551
+ package.extract_tar_gz tgz_io, destination_subdir
552
+ end
553
+
554
+ assert_path_exists destination_user_subdir
555
+
556
+ if Gem::Package::PathError === e
557
+ assert_equal("installing into parent path #{destination_user_subdir} of " +
558
+ "#{destination_subdir} is not allowed", e.message)
559
+ elsif win_platform?
560
+ skip "symlink - must be admin with no UAC on Windows"
561
+ else
562
+ raise e
563
+ end
564
+ end
565
+
529
566
  def test_extract_tar_gz_directory
530
567
  package = Gem::Package.new @gem
531
568
 
@@ -164,4 +164,45 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
164
164
  end
165
165
  end
166
166
 
167
+ def test_big_uid_gid
168
+ stream = StringIO.new(
169
+ <<-EOF.dup.force_encoding('binary').split("\n").join
170
+ GeoIP2-City_20190528/
171
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
172
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
173
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
174
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000000755\x00\x80\x00
175
+ \x00\x00v\xB2Z\x9E\x80\x00\x00\x00v\xB2Z\x9E00000000000\x0013473270100\x00015424
176
+ \x00 5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
177
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
178
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
179
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
180
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ustar \x00
181
+ tjmather\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
182
+ \x00\x00\x00\x00\x00tjmather\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
183
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
184
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
185
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
186
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
187
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
188
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
189
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
190
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
191
+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
192
+ \x00\x00\x00\x00
193
+ EOF
194
+ )
195
+
196
+ tar_header = Gem::Package::TarHeader.from stream
197
+
198
+ assert_equal 1991400094, tar_header.uid
199
+ assert_equal 1991400094, tar_header.gid
200
+
201
+ assert_equal 'GeoIP2-City_20190528/', tar_header.name
202
+ assert_equal 0755, tar_header.mode
203
+ assert_equal 0, tar_header.size
204
+ assert_equal 1559064640, tar_header.mtime
205
+ assert_equal 6932, tar_header.checksum
206
+ end
207
+
167
208
  end
@@ -11,9 +11,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
11
11
  @data = 'abcde12345'
12
12
  @io = TempIO.new
13
13
  @tar_writer = Gem::Package::TarWriter.new @io
14
+ @epoch = ENV["SOURCE_DATE_EPOCH"]
15
+ ENV["SOURCE_DATE_EPOCH"] = nil
14
16
  end
15
17
 
16
18
  def teardown
19
+ ENV["SOURCE_DATE_EPOCH"] = @epoch
17
20
  @tar_writer.close unless @tar_writer.closed?
18
21
  @io.close!
19
22