123456789_123456789_123456789_123456789_123456789_

Class: Gem::SafeMarshal::Reader

Relationships & Source Files
Namespace Children
Exceptions:
Inherits: Object
Defined in: lib/rubygems/safe_marshal/reader.rb

Constant Summary

Class Method Summary

Instance Method Summary

Constructor Details

.new(io) ⇒ Reader

[ GitHub ]

  
# File 'lib/rubygems/safe_marshal/reader.rb', line 29

def initialize(io)
  @io = io
end

Instance Method Details

#read!

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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 ]

  
# File 'lib/rubygems/safe_marshal/reader.rb', line 159

def read_false
  Elements::False::FALSE
end

#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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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 ]

  
# File 'lib/rubygems/safe_marshal/reader.rb', line 275

def read_nil
  Elements::Nil::NIL
end

#read_object (private)

[ GitHub ]

  
# 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_with_ivars (private)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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)

[ GitHub ]

  
# 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_true (private)

[ GitHub ]

  
# File 'lib/rubygems/safe_marshal/reader.rb', line 155

def read_true
  Elements::True::TRUE
end

#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