[rubygems/rubygems] Bundler error handling

https://github.com/rubygems/rubygems/commit/63b422b71a
This commit is contained in:
Samuel Giddins 2023-08-21 09:13:43 -07:00 коммит произвёл git
Родитель f0d1b0cc4b
Коммит e52f9bd41e
7 изменённых файлов: 66 добавлений и 14 удалений

Просмотреть файл

@ -517,7 +517,11 @@ EOF
def safe_load_marshal(data)
if Gem.respond_to?(:load_safe_marshal)
Gem.load_safe_marshal
Gem::SafeMarshal.safe_load(data)
begin
Gem::SafeMarshal.safe_load(data)
rescue Gem::SafeMarshal::Reader::Error, Gem::SafeMarshal::Visitors::ToRuby::Error => e
raise MarshalError, "#{e.class}: #{e.message}"
end
else
load_marshal(data, :marshal_proc => SafeMarshal.proc)
end

Просмотреть файл

@ -111,7 +111,7 @@ module Bundler
spec_file_name = "#{spec.join "-"}.gemspec"
uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz")
if uri.scheme == "file"
spec = if uri.scheme == "file"
path = Bundler.rubygems.correct_for_windows_path(uri.path)
Bundler.safe_load_marshal Bundler.rubygems.inflate(Gem.read_binary(path))
elsif cached_spec_path = gemspec_cached_path(spec_file_name)
@ -119,6 +119,8 @@ module Bundler
else
Bundler.safe_load_marshal Bundler.rubygems.inflate(downloader.fetch(uri).body)
end
raise MarshalError, "is #{spec.inspect}" unless spec.is_a?(Gem::Specification)
spec
rescue MarshalError
raise HTTPError, "Gemspec #{spec} contained invalid data.\n" \
"Your network or your gem server is probably having issues right now."

Просмотреть файл

@ -496,7 +496,9 @@ module Bundler
fetcher = gem_remote_fetcher
fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
string = fetcher.fetch_path(path)
Bundler.safe_load_marshal(string)
specs = Bundler.safe_load_marshal(string)
raise MarshalError, "Specs #{name} from #{remote} is expected to be an Array but was unexpected class #{specs.class}" unless specs.is_a?(Array)
specs
rescue Gem::RemoteFetcher::FetchError
# it's okay for prerelease to fail
raise unless name == "prerelease_specs"

Просмотреть файл

@ -62,7 +62,7 @@ module Gem
end
def self.load(input, permitted_classes: [::Symbol], permitted_symbols: [], permitted_ivars: {})
root = Reader.new(StringIO.new(input, "r")).read!
root = Reader.new(StringIO.new(input, "r").binmode).read!
Visitors::ToRuby.new(
permitted_classes: permitted_classes,

Просмотреть файл

@ -5,7 +5,16 @@ require_relative "elements"
module Gem
module SafeMarshal
class Reader
class UnconsumedBytesError < StandardError
class Error < StandardError
end
class UnsupportedVersionError < Error
end
class UnconsumedBytesError < Error
end
class NotImplementedError < Error
end
def initialize(io)
@ -26,7 +35,7 @@ module Gem
def read_header
v = @io.read(2)
raise "Unsupported marshal version #{v.inspect}, expected #{MARSHAL_VERSION.inspect}" unless v == MARSHAL_VERSION
raise UnsupportedVersionError, "Unsupported marshal version #{v.bytes.map(&:ord).join(".")}, expected #{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" unless v == MARSHAL_VERSION
end
def read_byte
@ -80,7 +89,7 @@ module Gem
when 91 then read_array # ?[
when 102 then read_float # ?f
when 105 then Elements::Integer.new int: read_integer # ?i
when 108 then read_bignum
when 108 then read_bignum # ?l
when 111 then read_object # ?o
when 117 then read_user_defined # ?u
when 123 then read_hash # ?{
@ -94,7 +103,7 @@ module Gem
when "S".ord then read_struct
when "C".ord then read_user_class
else
raise "Unsupported marshal type discriminator #{type.chr.inspect} (#{type})"
raise Error, "Unknown marshal type discriminator #{type.chr.inspect} (#{type})"
end
end
@ -177,6 +186,38 @@ module Gem
def read_bignum
Elements::Bignum.new(sign: read_byte, data: @io.read(read_integer * 2))
end
def read_extended_object
raise NotImplementedError, "Reading Marshal objects of type extended_object is not implemented"
end
def read_class
raise NotImplementedError, "Reading Marshal objects of type class is not implemented"
end
def read_module
raise NotImplementedError, "Reading Marshal objects of type module is not implemented"
end
def read_class_or_module
raise NotImplementedError, "Reading Marshal objects of type class_or_module is not implemented"
end
def read_data
raise NotImplementedError, "Reading Marshal objects of type data is not implemented"
end
def read_regexp
raise NotImplementedError, "Reading Marshal objects of type regexp is not implemented"
end
def read_struct
raise NotImplementedError, "Reading Marshal objects of type struct is not implemented"
end
def read_user_class
raise NotImplementedError, "Reading Marshal objects of type user_class is not implemented"
end
end
end
end

Просмотреть файл

@ -305,7 +305,10 @@ module Gem::SafeMarshal
raise MethodCallError, "Unable to call #{method.inspect} on #{receiver.inspect}, perhaps it is a class using marshal compat, which is not visible in ruby? #{e}"
end
class UnpermittedSymbolError < StandardError
class Error < StandardError
end
class UnpermittedSymbolError < Error
def initialize(symbol:, stack:)
@symbol = symbol
@stack = stack
@ -313,7 +316,7 @@ module Gem::SafeMarshal
end
end
class UnpermittedIvarError < StandardError
class UnpermittedIvarError < Error
def initialize(symbol:, klass:, stack:)
@symbol = symbol
@klass = klass
@ -322,7 +325,7 @@ module Gem::SafeMarshal
end
end
class UnpermittedClassError < StandardError
class UnpermittedClassError < Error
def initialize(name:, stack:)
@name = name
@stack = stack
@ -330,10 +333,10 @@ module Gem::SafeMarshal
end
end
class FormatError < StandardError
class FormatError < Error
end
class MethodCallError < StandardError
class MethodCallError < Error
end
end
end

Просмотреть файл

@ -23,7 +23,7 @@ RSpec.describe Bundler do
end
it "loads simple structure" do
simple_structure = { "name" => [:abc] }
simple_structure = { "name" => [:development] }
data = Marshal.dump(simple_structure)
expect(Bundler.safe_load_marshal(data)).to eq(simple_structure)
end