summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-19 08:27:04 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-19 08:27:04 +0000
commit90df7a08e41dba0e529eea8675f86ccdf6502597 (patch)
tree511b5dd540ce065fc379c6b2382420e9cf90f036 /lib
parent6d6880ff40d96a139fff156a7674b87978d321dc (diff)
merge revision(s) 62244,62246,62301,62302,62303,62422,62436,62452: [Backport #14481]
Merge RubyGems-2.7.5 from upstream. Please see its details: http://blog.rubygems.org/2018/02/06/2.7.5-released.html test_gem_util.rb: fix broken test * test/rubygems/test_gem_util.rb: no guarantee that tmpdir is always underneath the root directory at all. test_gem_commands_setup_command.rb: BUNDLER_VERS * test/rubygems/test_gem_commands_setup_command.rb: run bundled gem command, instead of installed one. no need to set bundled bundler unless Gem::USE_BUNDLER_FOR_GEMDEPS revert r62302 and force to define the version constant Merge RubyGems 2.7.6 from upstream. It fixed some security vulnerabilities. http://blog.rubygems.org/2018/02/15/2.7.6-released.html fix regexp literal warning. test/rubygems/test_gem_server.rb: eliminate duplicated character class warning. [Bug #14481] Remove unnecessary `[]`s git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_5@62837 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib')
-rw-r--r--lib/rubygems.rb12
-rw-r--r--lib/rubygems/commands/generate_index_command.rb2
-rw-r--r--lib/rubygems/commands/owner_command.rb2
-rw-r--r--lib/rubygems/commands/setup_command.rb29
-rw-r--r--lib/rubygems/commands/unpack_command.rb4
-rw-r--r--lib/rubygems/config_file.rb2
-rw-r--r--lib/rubygems/ext/builder.rb2
-rw-r--r--lib/rubygems/indexer.rb9
-rw-r--r--lib/rubygems/installer.rb13
-rw-r--r--lib/rubygems/package.rb41
-rw-r--r--lib/rubygems/package/file_source.rb4
-rw-r--r--lib/rubygems/package/old.rb2
-rw-r--r--lib/rubygems/package/tar_header.rb23
-rw-r--r--lib/rubygems/package/tar_writer.rb2
-rw-r--r--lib/rubygems/request_set/lockfile.rb2
-rw-r--r--lib/rubygems/security.rb2
-rw-r--r--lib/rubygems/security/trust_dir.rb2
-rw-r--r--lib/rubygems/server.rb14
-rw-r--r--lib/rubygems/source.rb2
-rw-r--r--lib/rubygems/specification.rb15
-rw-r--r--lib/rubygems/stub_specification.rb2
-rw-r--r--lib/rubygems/test_case.rb10
-rw-r--r--lib/rubygems/test_utilities.rb2
-rw-r--r--lib/rubygems/util.rb3
-rw-r--r--lib/rubygems/validator.rb6
25 files changed, 143 insertions, 64 deletions
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index 0475ced164..2762bfcb88 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -10,7 +10,7 @@ require 'rbconfig'
require 'thread'
module Gem
- VERSION = "2.7.3"
+ VERSION = "2.7.6"
end
# Must be first since it unloads the prelude from 1.9.2
@@ -161,7 +161,7 @@ module Gem
# these are defined in Ruby 1.8.7, hence the need for this convoluted setup.
READ_BINARY_ERRORS = begin
- read_binary_errors = [Errno::EACCES, Errno::EROFS]
+ read_binary_errors = [Errno::EACCES, Errno::EROFS, Errno::ENOSYS]
read_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP)
read_binary_errors
end.freeze
@@ -171,7 +171,7 @@ module Gem
# these are defined in Ruby 1.8.7.
WRITE_BINARY_ERRORS = begin
- write_binary_errors = []
+ write_binary_errors = [Errno::ENOSYS]
write_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP)
write_binary_errors
end.freeze
@@ -871,19 +871,19 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Safely read a file in binary mode on all platforms.
def self.read_binary(path)
- open path, 'rb+' do |f|
+ File.open path, 'rb+' do |f|
f.flock(File::LOCK_EX)
f.read
end
rescue *READ_BINARY_ERRORS
- open path, 'rb' do |f|
+ File.open path, 'rb' do |f|
f.read
end
rescue Errno::ENOLCK # NFS
if Thread.main != Thread.current
raise
else
- open path, 'rb' do |f|
+ File.open path, 'rb' do |f|
f.read
end
end
diff --git a/lib/rubygems/commands/generate_index_command.rb b/lib/rubygems/commands/generate_index_command.rb
index 01f1f88405..0b677b73a9 100644
--- a/lib/rubygems/commands/generate_index_command.rb
+++ b/lib/rubygems/commands/generate_index_command.rb
@@ -68,7 +68,7 @@ Marshal::MINOR_VERSION constants. It is used to ensure compatibility.
if not File.exist?(options[:directory]) or
not File.directory?(options[:directory]) then
- alert_error "unknown directory name #{directory}."
+ alert_error "unknown directory name #{options[:directory]}."
terminate_interaction 1
else
indexer = Gem::Indexer.new options.delete(:directory), options
diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb
index 8e2271657a..637b5bdc4d 100644
--- a/lib/rubygems/commands/owner_command.rb
+++ b/lib/rubygems/commands/owner_command.rb
@@ -64,7 +64,7 @@ permission to.
end
with_response response do |resp|
- owners = YAML.load resp.body
+ owners = Gem::SafeYAML.load resp.body
say "Owners for gem: #{name}"
owners.each do |owner|
diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 5d1414d102..ee6ce88eae 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -350,7 +350,9 @@ By default, this RubyGems will install gem as:
def install_default_bundler_gem
return unless Gem::USE_BUNDLER_FOR_GEMDEPS
- mkdir_p Gem::Specification.default_specifications_dir
+ specs_dir = Gem::Specification.default_specifications_dir
+ specs_dir = File.join(options[:destdir], specs_dir) unless Gem.win_platform?
+ mkdir_p specs_dir
# Workaround for non-git environment.
gemspec = File.open('bundler/bundler.gemspec', 'rb'){|f| f.read.gsub(/`git ls-files -z`/, "''") }
@@ -359,23 +361,36 @@ By default, this RubyGems will install gem as:
bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
bundler_spec.files = Dir.chdir("bundler") { Dir["{*.md,{lib,exe,man}/**/*}"] }
bundler_spec.executables -= %w[bundler bundle_ruby]
- Dir.entries(Gem::Specification.default_specifications_dir).
+
+ # Remove bundler-*.gemspec in default specification directory.
+ Dir.entries(specs_dir).
select {|gs| gs.start_with?("bundler-") }.
- each {|gs| File.delete(File.join(Gem::Specification.default_specifications_dir, gs)) }
+ each {|gs| File.delete(File.join(specs_dir, gs)) }
- default_spec_path = File.join(Gem::Specification.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
+ default_spec_path = File.join(specs_dir, "#{bundler_spec.full_name}.gemspec")
Gem.write_binary(default_spec_path, bundler_spec.to_ruby)
bundler_spec = Gem::Specification.load(default_spec_path)
+ # Remove gemspec that was same version of vendored bundler.
+ normal_gemspec = File.join(Gem.default_dir, "specifications", "bundler-#{bundler_spec.version}.gemspec")
+ if File.file? normal_gemspec
+ File.delete normal_gemspec
+ end
+
+ # Remove gem files that were same version of vendored bundler.
if File.directory? bundler_spec.gems_dir
Dir.entries(bundler_spec.gems_dir).
- select {|default_gem| File.basename(default_gem).match(/^bundler-#{Gem::Version::VERSION_PATTERN}$/) }.
+ select {|default_gem| File.basename(default_gem) == "bundler-#{bundler_spec.version}" }.
each {|default_gem| rm_r File.join(bundler_spec.gems_dir, default_gem) }
end
- mkdir_p bundler_spec.bin_dir
- bundler_spec.executables.each {|e| cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_spec.bin_dir, e) }
+ bundler_bin_dir = File.join(Gem.default_dir, 'gems', bundler_spec.full_name, bundler_spec.bindir)
+ bundler_bin_dir = File.join(options[:destdir], bundler_bin_dir) unless Gem.win_platform?
+ mkdir_p bundler_bin_dir
+ bundler_spec.executables.each do |e|
+ cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e)
+ end
if Gem.win_platform?
require 'rubygems/installer'
diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb
index eb7f550673..b873f20d28 100644
--- a/lib/rubygems/commands/unpack_command.rb
+++ b/lib/rubygems/commands/unpack_command.rb
@@ -94,7 +94,7 @@ command help for an example.
spec_file = File.basename spec.spec_file
- open spec_file, 'w' do |io|
+ File.open spec_file, 'w' do |io|
io.write metadata
end
else
@@ -176,7 +176,7 @@ command help for an example.
metadata = nil
- open path, Gem.binary_mode do |io|
+ File.open path, Gem.binary_mode do |io|
tar = Gem::Package::TarReader.new io
tar.each_entry do |entry|
case entry.full_name
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index a4efed0f5a..c0d19dbfc2 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -458,7 +458,7 @@ if you believe they were disclosed to a third party.
# Writes out this config file, replacing its source.
def write
- open config_file_name, 'w' do |io|
+ File.open config_file_name, 'w' do |io|
io.write to_yaml
end
end
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb
index a1619c97d7..eb9db199d5 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -212,7 +212,7 @@ EOF
FileUtils.mkdir_p @spec.extension_dir
- open destination, 'wb' do |io| io.puts output end
+ File.open destination, 'wb' do |io| io.puts output end
destination
end
diff --git a/lib/rubygems/indexer.rb b/lib/rubygems/indexer.rb
index 871cc09d8d..3ea994414b 100644
--- a/lib/rubygems/indexer.rb
+++ b/lib/rubygems/indexer.rb
@@ -2,6 +2,7 @@
require 'rubygems'
require 'rubygems/package'
require 'time'
+require 'tmpdir'
begin
gem 'builder'
@@ -64,7 +65,7 @@ class Gem::Indexer
@build_modern = options[:build_modern]
@dest_directory = directory
- @directory = File.join(Dir.tmpdir, "gem_generate_index_#{$$}")
+ @directory = Dir.mktmpdir 'gem_generate_index'
marshal_name = "Marshal.#{Gem.marshal_version}"
@@ -123,7 +124,7 @@ class Gem::Indexer
marshal_name = File.join @quick_marshal_dir, spec_file_name
marshal_zipped = Gem.deflate Marshal.dump(spec)
- open marshal_name, 'wb' do |io| io.write marshal_zipped end
+ File.open marshal_name, 'wb' do |io| io.write marshal_zipped end
files << marshal_name
@@ -261,7 +262,7 @@ class Gem::Indexer
zipped = Gem.deflate data
- open "#{filename}.#{extension}", 'wb' do |io|
+ File.open "#{filename}.#{extension}", 'wb' do |io|
io.write zipped
end
end
@@ -427,7 +428,7 @@ class Gem::Indexer
specs_index = compact_specs specs_index.uniq.sort
- open dest, 'wb' do |io|
+ File.open dest, 'wb' do |io|
Marshal.dump specs_index, io
end
end
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 0cbca0791b..ee5fedeb64 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -206,7 +206,7 @@ class Gem::Installer
ruby_executable = false
existing = nil
- open generated_bin, 'rb' do |io|
+ File.open generated_bin, 'rb' do |io|
next unless io.gets =~ /^#!/ # shebang
io.gets # blankline
@@ -427,7 +427,7 @@ class Gem::Installer
# specifications directory.
def write_spec
- open spec_file, 'w' do |file|
+ File.open spec_file, 'w' do |file|
spec.installed_by_version = Gem.rubygems_version
file.puts spec.to_ruby_for_cache
@@ -464,7 +464,12 @@ class Gem::Installer
def generate_bin # :nodoc:
return if spec.executables.nil? or spec.executables.empty?
- Dir.mkdir @bin_dir unless File.exist? @bin_dir
+ begin
+ Dir.mkdir @bin_dir
+ rescue SystemCallError
+ raise unless File.directory? @bin_dir
+ end
+
raise Gem::FilePermissionError.new(@bin_dir) unless File.writable? @bin_dir
spec.executables.each do |filename|
@@ -863,7 +868,7 @@ TEXT
build_info_file = File.join build_info_dir, "#{spec.full_name}.info"
- open build_info_file, 'w' do |io|
+ File.open build_info_file, 'w' do |io|
@build_args.each do |arg|
io.puts arg
end
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index 77811ed5ec..b924122827 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -219,7 +219,7 @@ class Gem::Package
next unless stat.file?
tar.add_file_simple file, stat.mode, stat.size do |dst_io|
- open file, 'rb' do |src_io|
+ File.open file, 'rb' do |src_io|
dst_io.write src_io.read 16384 until src_io.eof?
end
end
@@ -378,9 +378,9 @@ EOM
File.dirname destination
end
- FileUtils.mkdir_p mkdir, mkdir_options
+ mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name
- open destination, 'wb' do |out|
+ File.open destination, 'wb' do |out|
out.write entry.read
FileUtils.chmod entry.header.mode, destination
end if entry.file?
@@ -416,20 +416,35 @@ EOM
raise Gem::Package::PathError.new(filename, destination_dir) if
filename.start_with? '/'
- destination_dir = File.realpath destination_dir if
- File.respond_to? :realpath
+ destination_dir = realpath destination_dir
destination_dir = File.expand_path destination_dir
destination = File.join destination_dir, filename
destination = File.expand_path destination
raise Gem::Package::PathError.new(destination, destination_dir) unless
- destination.start_with? destination_dir
+ destination.start_with? destination_dir + '/'
destination.untaint
destination
end
+ def mkdir_p_safe mkdir, mkdir_options, destination_dir, file_name
+ destination_dir = realpath File.expand_path(destination_dir)
+ parts = mkdir.split(File::SEPARATOR)
+ parts.reduce do |path, basename|
+ path = realpath path unless path == ""
+ path = File.expand_path(path + File::SEPARATOR + basename)
+ lstat = File.lstat path rescue nil
+ if !lstat || !lstat.directory?
+ unless path.start_with? destination_dir and (FileUtils.mkdir path, mkdir_options rescue false)
+ raise Gem::Package::PathError.new(file_name, destination_dir)
+ end
+ end
+ path
+ end
+ end
+
##
# Loads a Gem::Specification from the TarEntry +entry+
@@ -603,6 +618,10 @@ EOM
raise Gem::Package::FormatError.new \
'package content (data.tar.gz) is missing', @gem
end
+
+ if duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first) and duplicates.any?
+ raise Gem::Security::Exception, "duplicate files in the package: (#{duplicates.map(&:inspect).join(', ')})"
+ end
end
##
@@ -616,6 +635,16 @@ EOM
raise Gem::Package::FormatError.new(e.message, entry.full_name)
end
+ if File.respond_to? :realpath
+ def realpath file
+ File.realpath file
+ end
+ else
+ def realpath file
+ file
+ end
+ end
+
end
require 'rubygems/package/digest_io'
diff --git a/lib/rubygems/package/file_source.rb b/lib/rubygems/package/file_source.rb
index 1a4dc4c824..ecc3a68677 100644
--- a/lib/rubygems/package/file_source.rb
+++ b/lib/rubygems/package/file_source.rb
@@ -23,11 +23,11 @@ class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all
end
def with_write_io &block
- open path, 'wb', &block
+ File.open path, 'wb', &block
end
def with_read_io &block
- open path, 'rb', &block
+ File.open path, 'rb', &block
end
end
diff --git a/lib/rubygems/package/old.rb b/lib/rubygems/package/old.rb
index f6e6e67c38..322d682ca8 100644
--- a/lib/rubygems/package/old.rb
+++ b/lib/rubygems/package/old.rb
@@ -80,7 +80,7 @@ class Gem::Package::Old < Gem::Package
FileUtils.mkdir_p File.dirname destination
- open destination, 'wb', entry['mode'] do |out|
+ File.open destination, 'wb', entry['mode'] do |out|
out.write file_data
end
diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb
index c54bd14d57..d557357114 100644
--- a/lib/rubygems/package/tar_header.rb
+++ b/lib/rubygems/package/tar_header.rb
@@ -104,25 +104,30 @@ class Gem::Package::TarHeader
fields = header.unpack UNPACK_FORMAT
new :name => fields.shift,
- :mode => fields.shift.oct,
- :uid => fields.shift.oct,
- :gid => fields.shift.oct,
- :size => fields.shift.oct,
- :mtime => fields.shift.oct,
- :checksum => fields.shift.oct,
+ :mode => strict_oct(fields.shift),
+ :uid => strict_oct(fields.shift),
+ :gid => strict_oct(fields.shift),
+ :size => strict_oct(fields.shift),
+ :mtime => strict_oct(fields.shift),
+ :checksum => strict_oct(fields.shift),
:typeflag => fields.shift,
:linkname => fields.shift,
:magic => fields.shift,
- :version => fields.shift.oct,
+ :version => strict_oct(fields.shift),
:uname => fields.shift,
:gname => fields.shift,
- :devmajor => fields.shift.oct,
- :devminor => fields.shift.oct,
+ :devmajor => strict_oct(fields.shift),
+ :devminor => strict_oct(fields.shift),
:prefix => fields.shift,
:empty => empty
end
+ def self.strict_oct(str)
+ return str.oct if str =~ /\A[0-7]*\z/
+ raise ArgumentError, "#{str.inspect} is not an octal string"
+ end
+
##
# Creates a new TarHeader using +vals+
diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb
index f68b8d4c5e..390f7851a3 100644
--- a/lib/rubygems/package/tar_writer.rb
+++ b/lib/rubygems/package/tar_writer.rb
@@ -196,6 +196,8 @@ class Gem::Package::TarWriter
digest_name == signer.digest_name
end
+ raise "no #{signer.digest_name} in #{digests.values.compact}" unless signature_digest
+
if signer.key then
signature = signer.sign signature_digest.digest
diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb
index 7f6eadb939..76ad17d486 100644
--- a/lib/rubygems/request_set/lockfile.rb
+++ b/lib/rubygems/request_set/lockfile.rb
@@ -223,7 +223,7 @@ class Gem::RequestSet::Lockfile
def write
content = to_s
- open "#{@gem_deps_file}.lock", 'w' do |io|
+ File.open "#{@gem_deps_file}.lock", 'w' do |io|
io.write content
end
end
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
index 4690dd9230..236577c5a3 100644
--- a/lib/rubygems/security.rb
+++ b/lib/rubygems/security.rb
@@ -578,7 +578,7 @@ module Gem::Security
def self.write pemmable, path, permissions = 0600, passphrase = nil, cipher = KEY_CIPHER
path = File.expand_path path
- open path, 'wb', permissions do |io|
+ File.open path, 'wb', permissions do |io|
if passphrase and cipher
io.write pemmable.to_pem cipher, passphrase
else
diff --git a/lib/rubygems/security/trust_dir.rb b/lib/rubygems/security/trust_dir.rb
index bf44975cc6..849cf3cd3e 100644
--- a/lib/rubygems/security/trust_dir.rb
+++ b/lib/rubygems/security/trust_dir.rb
@@ -93,7 +93,7 @@ class Gem::Security::TrustDir
destination = cert_path certificate
- open destination, 'wb', @permissions[:trusted_cert] do |io|
+ File.open destination, 'wb', @permissions[:trusted_cert] do |io|
io.write certificate.to_pem
end
end
diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb
index 93b3af36f8..62c3dfe9cf 100644
--- a/lib/rubygems/server.rb
+++ b/lib/rubygems/server.rb
@@ -623,6 +623,18 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
executables = nil if executables.empty?
executables.last["is_last"] = true if executables
+ # Pre-process spec homepage for safety reasons
+ begin
+ homepage_uri = URI.parse(spec.homepage)
+ if [URI::HTTP, URI::HTTPS].member? homepage_uri.class
+ homepage_uri = spec.homepage
+ else
+ homepage_uri = "."
+ end
+ rescue URI::InvalidURIError
+ homepage_uri = "."
+ end
+
specs << {
"authors" => spec.authors.sort.join(", "),
"date" => spec.date.to_s,
@@ -632,7 +644,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
"only_one_executable" => (executables && executables.size == 1),
"full_name" => spec.full_name,
"has_deps" => !deps.empty?,
- "homepage" => spec.homepage,
+ "homepage" => homepage_uri,
"name" => spec.name,
"rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?,
"ri_installed" => Gem::RDoc.new(spec).ri_installed?,
diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb
index bd84c217a7..b28b850660 100644
--- a/lib/rubygems/source.rb
+++ b/lib/rubygems/source.rb
@@ -160,7 +160,7 @@ class Gem::Source
if update_cache? then
FileUtils.mkdir_p cache_dir
- open local_spec, 'wb' do |io|
+ File.open local_spec, 'wb' do |io|
io.write spec
end
end
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index efc08c4738..2560324b7a 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -15,6 +15,7 @@ require 'rubygems/basic_specification'
require 'rubygems/stub_specification'
require 'rubygems/util/list'
require 'stringio'
+require 'uri'
##
# The Specification class contains the information for a Gem. Typically
@@ -2822,10 +2823,16 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
raise Gem::InvalidSpecificationException, "#{lazy} is not a summary"
end
- if homepage and not homepage.empty? and
- homepage !~ /\A[a-z][a-z\d+.-]*:/i then
- raise Gem::InvalidSpecificationException,
- "\"#{homepage}\" is not a URI"
+ # Make sure a homepage is valid HTTP/HTTPS URI
+ if homepage and not homepage.empty?
+ begin
+ homepage_uri = URI.parse(homepage)
+ unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class
+ raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI"
+ end
+ rescue URI::InvalidURIError
+ raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI"
+ end
end
# Warnings
diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb
index 8337375ab4..ae2effbc84 100644
--- a/lib/rubygems/stub_specification.rb
+++ b/lib/rubygems/stub_specification.rb
@@ -113,6 +113,8 @@ class Gem::StubSpecification < Gem::BasicSpecification
unless @data
begin
saved_lineno = $.
+
+ # TODO It should be use `File.open`, but bundler-1.16.1 example expects Kernel#open.
open loaded_from, OPEN_MODE do |file|
begin
file.readline # discard encoding line
diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb
index f7f216e5e3..39aa4fc9a7 100644
--- a/lib/rubygems/test_case.rb
+++ b/lib/rubygems/test_case.rb
@@ -488,7 +488,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
gemspec = "#{name}.gemspec"
- open File.join(directory, gemspec), 'w' do |io|
+ File.open File.join(directory, gemspec), 'w' do |io|
io.write git_spec.to_ruby
end
@@ -592,7 +592,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
# Reads a Marshal file at +path+
def read_cache(path)
- open path.dup.untaint, 'rb' do |io|
+ File.open path.dup.untaint, 'rb' do |io|
Marshal.load io.read
end
end
@@ -612,7 +612,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
dir = File.dirname path
FileUtils.mkdir_p dir unless File.directory? dir
- open path, 'wb' do |io|
+ File.open path, 'wb' do |io|
yield io if block_given?
end
@@ -727,7 +727,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
install_default_specs(*specs)
specs.each do |spec|
- open spec.loaded_from, 'w' do |io|
+ File.open spec.loaded_from, 'w' do |io|
io.write spec.to_ruby_for_cache
end
end
@@ -1363,7 +1363,7 @@ Also, a list:
yield specification if block_given?
end
- open File.join(directory, "#{name}.gemspec"), 'w' do |io|
+ File.open File.join(directory, "#{name}.gemspec"), 'w' do |io|
io.write vendor_spec.to_ruby
end
diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb
index 686916ea02..83c9d2d0fe 100644
--- a/lib/rubygems/test_utilities.rb
+++ b/lib/rubygems/test_utilities.rb
@@ -346,7 +346,7 @@ class Gem::TestCase::SpecFetcherSetup
end
def write_spec spec # :nodoc:
- open spec.spec_file, 'w' do |io|
+ File.open spec.spec_file, 'w' do |io|
io.write spec.to_ruby_for_cache
end
end
diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb
index 2de45c900b..6c75910004 100644
--- a/lib/rubygems/util.rb
+++ b/lib/rubygems/util.rb
@@ -114,7 +114,8 @@ module Gem::Util
here = File.expand_path directory
loop do
- Dir.chdir here, &block
+ Dir.chdir here, &block rescue Errno::EACCES
+
new_here = File.expand_path('..', here)
return if new_here == here # toplevel
here = new_here
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 83448229bb..6842e4fa9c 100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -34,7 +34,7 @@ class Gem::Validator
# gem_path:: [String] Path to gem file
def verify_gem_file(gem_path)
- open gem_path, Gem.binary_mode do |file|
+ File.open gem_path, Gem.binary_mode do |file|
gem_data = file.read
verify_gem gem_data
end
@@ -109,7 +109,7 @@ class Gem::Validator
good, gone, unreadable = nil, nil, nil, nil
- open gem_path, Gem.binary_mode do |file|
+ File.open gem_path, Gem.binary_mode do |file|
package = Gem::Package.new gem_path
good, gone = package.contents.partition { |file_name|
@@ -134,7 +134,7 @@ class Gem::Validator
source = File.join gem_directory, entry['path']
- open source, Gem.binary_mode do |f|
+ File.open source, Gem.binary_mode do |f|
unless f.read == data then
errors[gem_name][entry['path']] = "Modified from original"
end