Class: Gem::SafeMarshal::Reader
Relationships & Source Files | |
Namespace Children | |
Exceptions:
| |
Inherits: | Object |
Defined in: | lib/rubygems/safe_marshal/reader.rb |
Constant Summary
-
EMPTY_ARRAY =
private
# File 'lib/rubygems/safe_marshal/reader.rb', line 169Elements::Array.new([].freeze).freeze
-
EMPTY_HASH =
private
# File 'lib/rubygems/safe_marshal/reader.rb', line 242Elements::Hash.new([].freeze).freeze
-
EMPTY_STRING =
private
# File 'lib/rubygems/safe_marshal/reader.rb', line 145Elements::String.new("".b.freeze).freeze
-
MARSHAL_VERSION =
private
# File 'lib/rubygems/safe_marshal/reader.rb', line 42[Marshal::MAJOR_VERSION, Marshal::MINOR_VERSION].map(&:chr).join.freeze
-
OBJECT_LINKS =
private
profiling bundle install –full-index shows that offset 6 is by far the most common object link, so we special case it to avoid allocating a new object a third of the time. the following are all the object links that appear more than 10000 times in my profiling
{ 6 => Elements::ObjectLink.new(6).freeze, 30 => Elements::ObjectLink.new(30).freeze, 81 => Elements::ObjectLink.new(81).freeze, 34 => Elements::ObjectLink.new(34).freeze, 38 => Elements::ObjectLink.new(38).freeze, 50 => Elements::ObjectLink.new(50).freeze, 91 => Elements::ObjectLink.new(91).freeze, 42 => Elements::ObjectLink.new(42).freeze, 46 => Elements::ObjectLink.new(46).freeze, 150 => Elements::ObjectLink.new(150).freeze, 100 => Elements::ObjectLink.new(100).freeze, 104 => Elements::ObjectLink.new(104).freeze, 108 => Elements::ObjectLink.new(108).freeze, 242 => Elements::ObjectLink.new(242).freeze, 246 => Elements::ObjectLink.new(246).freeze, 139 => Elements::ObjectLink.new(139).freeze, 143 => Elements::ObjectLink.new(143).freeze, 114 => Elements::ObjectLink.new(114).freeze, 308 => Elements::ObjectLink.new(308).freeze, 200 => Elements::ObjectLink.new(200).freeze, 54 => Elements::ObjectLink.new(54).freeze, 62 => Elements::ObjectLink.new(62).freeze, 1_286_245 => Elements::ObjectLink.new(1_286_245).freeze, }.freeze
-
STRING_E_SYMBOL =
private
# File 'lib/rubygems/safe_marshal/reader.rb', line 127Elements::Symbol.new("E").freeze
Class Method Summary
- .new(io) ⇒ Reader constructor
Instance Method Summary
- #read!
- #read_array private
- #read_bignum private
- #read_byte private
- #read_bytes(n) private
- #read_class private
- #read_class_or_module private
- #read_data private
- #read_element private
- #read_extended_object private
- #read_false private
- #read_float private
- #read_hash private
- #read_hash_with_default_value private
- #read_header private
- #read_integer private
- #read_module private
- #read_nil private
- #read_object private
- #read_object_link private
- #read_object_with_ivars private
- #read_regexp private
- #read_string private
- #read_struct private
- #read_symbol private
- #read_symbol_link private
- #read_true private
- #read_user_class private
- #read_user_defined private
- #read_user_marshal private
Constructor Details
.new(io) ⇒ Reader
# File 'lib/rubygems/safe_marshal/reader.rb', line 29
def initialize(io) @io = io end
Instance Method Details
#read!
# File 'lib/rubygems/safe_marshal/reader.rb', line 33
def read! read_header root = read_element raise UnconsumedBytesError, "expected EOF, got #{@io.read(10).inspect}... after top-level element #{root.class}" unless @io.eof? root end
#read_array (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 172
def read_array length = read_integer return EMPTY_ARRAY if length == 0 raise NegativeLengthError if length < 0 elements = Array.new(length) do read_element end Elements::Array.new(elements) end
#read_bignum (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 284
def read_bignum sign = read_byte data = read_bytes(read_integer * 2) Elements::Bignum.new(sign, data) end
#read_byte (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 58
def read_byte @io.getbyte || raise(EOFError, "Unexpected EOF") end
#read_bytes(n) (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 50
def read_bytes(n) raise NegativeLengthError if n < 0 str = @io.read(n) raise EOFError, "expected #{n} bytes, got EOF" if str.nil? raise DataTooShortError, "expected #{n} bytes, got #{str.inspect}" unless str.bytesize == n str end
#read_class (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 294
def read_class raise NotImplementedError, "Reading Marshal objects of type class is not implemented" end
#read_class_or_module (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 302
def read_class_or_module raise NotImplementedError, "Reading Marshal objects of type class_or_module is not implemented" end
#read_data (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 306
def read_data raise NotImplementedError, "Reading Marshal objects of type data is not implemented" end
#read_element (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 94
def read_element type = read_byte case type when 34 then read_string # ?" when 48 then read_nil # ?0 when 58 then read_symbol # ?: when 59 then read_symbol_link # ?; when 64 then read_object_link # ?@ when 70 then read_false # ?F when 73 then read_object_with_ivars # ?I when 84 then read_true # ?T when 85 then read_user_marshal # ?U when 91 then read_array # ?[ when 102 then read_float # ?f when 105 then Elements::Integer.new(read_integer) # ?i when 108 then read_bignum # ?l when 111 then read_object # ?o when 117 then read_user_defined # ?u when 123 then read_hash # ?{ when 125 then read_hash_with_default_value # ?} when 101 then read_extended_object # ?e when 99 then read_class # ?c when 109 then read_module # ?m when 77 then read_class_or_module # ?M when 100 then read_data # ?d when 47 then read_regexp # ?/ when 83 then read_struct # ?S when 67 then read_user_class # ?C else raise Error, "Unknown marshal type discriminator #{type.chr.inspect} (#{type})" end end
#read_extended_object (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 290
def read_extended_object raise NotImplementedError, "Reading Marshal objects of type extended_object is not implemented" end
#read_false (private)
[ GitHub ]#read_float (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 279
def read_float string = read_bytes(read_integer) Elements::Float.new(string) end
#read_hash (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 245
def read_hash length = read_integer return EMPTY_HASH if length == 0 pairs = Array.new(length) do [read_element, read_element] end Elements::Hash.new(pairs) end
#read_hash_with_default_value (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 254
def read_hash_with_default_value length = read_integer raise NegativeLengthError if length < 0 pairs = Array.new(length) do [read_element, read_element] end default = read_element Elements::HashWithDefaultValue.new(pairs, default) end
#read_header (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 45
def read_header v = @io.read(2) raise UnsupportedVersionError, "Unsupported marshal version #{v.bytes.map(&:ord).join(".")}, expected #{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" unless v == MARSHAL_VERSION end
#read_integer (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 62
def read_integer b = read_byte case b when 0x00 0 when 0x01 read_byte when 0x02 read_byte | (read_byte << 8) when 0x03 read_byte | (read_byte << 8) | (read_byte << 16) when 0x04 read_byte | (read_byte << 8) | (read_byte << 16) | (read_byte << 24) when 0xFC read_byte | (read_byte << 8) | (read_byte << 16) | (read_byte << 24) | -0x100000000 when 0xFD read_byte | (read_byte << 8) | (read_byte << 16) | -0x1000000 when 0xFE read_byte | (read_byte << 8) | -0x10000 when 0xFF read_byte | -0x100 else signed = (b ^ 128) - 128 if b >= 128 signed + 5 else signed - 5 end end end
#read_module (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 298
def read_module raise NotImplementedError, "Reading Marshal objects of type module is not implemented" end
#read_nil (private)
[ GitHub ]#read_object (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 264
def read_object name = read_element object = Elements::Object.new(name) length = read_integer raise NegativeLengthError if length < 0 ivars = Array.new(length) do [read_element, read_element] end Elements::WithIvars.new(object, ivars) end
#read_object_link (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 237
def read_object_link offset = read_integer OBJECT_LINKS[offset] || Elements::ObjectLink.new(offset) end
#read_object_with_ivars (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 182
def read_object_with_ivars object = read_element length = read_integer raise NegativeLengthError if length < 0 ivars = Array.new(length) do [read_element, read_element] end Elements::WithIvars.new(object, ivars) end
#read_regexp (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 310
def read_regexp raise NotImplementedError, "Reading Marshal objects of type regexp is not implemented" end
#read_string (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 148
def read_string length = read_integer return EMPTY_STRING if length == 0 str = read_bytes(length) Elements::String.new(str) end
#read_struct (private)
# File 'lib/rubygems/safe_marshal/reader.rb', line 314
def read_struct raise NotImplementedError, "Reading Marshal objects of type struct is not implemented" end
#read_symbol (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 130
def read_symbol len = read_integer if len == 1 byte = read_byte if byte == 69 # ?E STRING_E_SYMBOL else Elements::Symbol.new(byte.chr) end else name = read_bytes(len) Elements::Symbol.new(name) end end
#read_symbol_link (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 192
def read_symbol_link offset = read_integer Elements::SymbolLink.new(offset) end
#read_true (private)
[ GitHub ]#read_user_class (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 318
def read_user_class name = read_element wrapped_object = read_element Elements::UserClass.new(name, wrapped_object) end
#read_user_defined (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 163
def read_user_defined name = read_element binary_string = read_bytes(read_integer) Elements::UserDefined.new(name, binary_string) end
#read_user_marshal (private)
[ GitHub ]# File 'lib/rubygems/safe_marshal/reader.rb', line 197
def read_user_marshal name = read_element data = read_element Elements::UserMarshal.new(name, data) end