Class: Python::Pickle::Protocol2

Inherits:
Protocol1 show all
Defined in:
lib/python/pickle/protocol2.rb

Direct Known Subclasses

Protocol3

Constant Summary collapse

OPCODES =

Opcodes for Pickle protocol version 2.

Protocol1::OPCODES + Set[
  128, # PROTO
  129, # NEWOBJ
  130, # EXT1
  131, # EXT2
  132, # EXT4
  133, # TUPLE1
  134, # TUPLE2
  135, # TUPLE3
  136, # NEWTRUE
  137, # NEWFALSE
  138, # LONG1
  139  # LONG4
]

Instance Attribute Summary

Attributes inherited from Protocol

#io

Instance Method Summary collapse

Methods inherited from Protocol1

#read_float64_be, #read_uint32_le, #read_uint8

Methods inherited from Protocol0

#read_escaped_char, #read_float, #read_hex_escaped_char, #read_int, #read_long, #read_nl_string, #read_string, #read_unicode_escaped_char, #read_unicode_escaped_char16, #read_unicode_escaped_char32, #read_unicode_string

Methods inherited from Protocol

#initialize, #read

Constructor Details

This class inherits a constructor from Python::Pickle::Protocol

Instance Method Details

#read_instructionInstruction

Reads an instruction from the pickle stream.

Returns:

  • The decoded instruction.

Raises:

  • The pickle stream could not be parsed.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/python/pickle/protocol2.rb', line 46

def read_instruction
  case (opcode = @io.getbyte)
  #
  # Protocol 0 instructions
  #
  when 40 # MARK
    Instructions::MARK
  when 46 # STOP
    Instructions::STOP
  when 48 # POP
    Instructions::POP
  when 49 # POP_MARK
    Instructions::POP_MARK
  when 50 # DUP
    Instructions::DUP
  when 70 # FLOAT
    Instructions::Float.new(read_float)
  when 73 # INT
    Instructions::Int.new(read_int)
  when 76 # LONG
    Instructions::Long.new(read_long)
  when 78 # NONE
    Instructions::NONE
  when 82 # REDUCE
    Instructions::REDUCE
  when 83 # STRING
    Instructions::String.new(read_string)
  when 86 # UNICODE
    Instructions::String.new(read_unicode_string)
  when 97 # APPEND
    Instructions::APPEND
  when 98 # BUILD
    Instructions::BUILD
  when 99 # GLOBAL
    Instructions::Global.new(read_nl_string,read_nl_string)
  when 100 # DICT
    Instructions::DICT
  when 103 # GET
    Instructions::Get.new(read_int)
  when 108 # LIST
    Instructions::LIST
  when 112 # PUT
    Instructions::Put.new(read_int)
  when 115 # SETITEM
    Instructions::SETITEM
  when 116 # TUPLE
    Instructions::TUPLE
  #
  # Protocol 1 instructions
  #
  when 41  # EMPTY_TUPLE
    Instructions::EMPTY_TUPLE
  when 71  # BINFLOAT
    Instructions::BinFloat.new(read_float64_be)
  when 75  # BININT1
    Instructions::BinInt1.new(read_uint8)
  when 84  # BINSTRING
    length = read_uint32_le
    string = @io.read(length)

    Instructions::BinString.new(length,string)
  when 85  # SHORT_BINSTRING
    length = read_uint8
    string = @io.read(length)

    Instructions::ShortBinString.new(length,string)
  when 88  # BINUNICODE
    length = read_uint32_le
    string = @io.read(length).force_encoding(Encoding::UTF_8)

    Instructions::BinUnicode.new(length,string)
  when 93  # EMPTY_LIST
    Instructions::EMPTY_LIST
  when 101 # APPENDS
    Instructions::APPENDS
  when 104 # BINGET
    Instructions::BinGet.new(read_uint8)
  when 106 # LONG_BINGET
    Instructions::LongBinGet.new(read_uint32_le)
  when 113 # BINPUT
    Instructions::BinPut.new(read_uint8)
  when 117 # SETITEMS
    Instructions::SETITEMS
  when 125 # EMPTY_DICT
    Instructions::EMPTY_DICT
  #
  # Protocol 2 instructions
  #
  when 128 # PROT
    Instructions::Proto.new(read_uint8)
  when 129 # NEWOBJ
    Instructions::NEWOBJ
  when 130 # EXT1
    Instructions::Ext1.new(read_uint8)
  when 131 # EXT2
    Instructions::Ext2.new(read_uint16_le)
  when 132 # EXT4
    Instructions::Ext4.new(read_uint32_le)
  when 133 # TUPLE1
    Instructions::TUPLE1
  when 134 # TUPLE2
    Instructions::TUPLE2
  when 135 # TUPLE3
    Instructions::TUPLE3
  when 136 # NEWTRUE
    Instructions::NEWTRUE
  when 137 # NEWFALSE
    Instructions::NEWFALSE
  when 138 # LONG1
    length = read_uint8
    long   = read_int_le(length)

    Instructions::Long1.new(length,long)
  when 139 # LONG4
    length = read_uint32_le
    long   = read_int_le(length)

    Instructions::Long4.new(length,long)
  else
    raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 2")
  end
end

#read_int_le(length) ⇒ Integer

Reads and unpacks a signed integer of arbitrary length.

Parameters:

  • The number of bytes to read.

Returns:

  • The decoded long integer.



188
189
190
191
192
193
194
195
196
# File 'lib/python/pickle/protocol2.rb', line 188

def read_int_le(length)
  data = @io.read(length)

  if data.bytesize < length
    raise(InvalidFormat,"premature end of string")
  end

  return unpack_int_le(data)
end

#read_uint16_leInteger

Reads an unsigned 16bit integer in little-endian byte-order.

Returns:

  • The decoded integer.



175
176
177
# File 'lib/python/pickle/protocol2.rb', line 175

def read_uint16_le
  @io.read(2).unpack1('S<')
end

#unpack_int_le(data) ⇒ Integer

Decodes a packed twos-complement long value of arbitrary length.

Parameters:

  • The packed long to decode.

Returns:

  • The unpacked long.



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/python/pickle/protocol2.rb', line 207

def unpack_int_le(data)
  return 0 if data.empty?

  long  = 0
  shift = 0

  data.each_byte do |b|
    long |= b << shift
    shift += 8
  end

  max_signed = (1 << (shift-1))

  if long >= max_signed
    long -= (1 << shift)
  end

  return long
end