python-pickle 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +17 -0
  3. data/README.md +4 -1
  4. data/lib/python/pickle/deserializer.rb +142 -80
  5. data/lib/python/pickle/instructions/bin_persid.rb +31 -0
  6. data/lib/python/pickle/instructions/global.rb +11 -41
  7. data/lib/python/pickle/instructions/has_namespace_and_name.rb +61 -0
  8. data/lib/python/pickle/instructions/inst.rb +34 -0
  9. data/lib/python/pickle/instructions/next_buffer.rb +5 -1
  10. data/lib/python/pickle/instructions/obj.rb +30 -0
  11. data/lib/python/pickle/instructions/persid.rb +31 -0
  12. data/lib/python/pickle/instructions/readonly_buffer.rb +4 -0
  13. data/lib/python/pickle/instructions.rb +64 -0
  14. data/lib/python/pickle/protocol0.rb +313 -68
  15. data/lib/python/pickle/protocol1.rb +225 -93
  16. data/lib/python/pickle/protocol2.rb +205 -124
  17. data/lib/python/pickle/protocol3.rb +92 -123
  18. data/lib/python/pickle/protocol4.rb +188 -165
  19. data/lib/python/pickle/protocol5.rb +98 -166
  20. data/lib/python/pickle/version.rb +1 -1
  21. data/lib/python/pickle.rb +71 -39
  22. data/spec/deserializer_spec.rb +359 -0
  23. data/spec/fixtures/set_v0.pkl +11 -0
  24. data/spec/fixtures/set_v1.pkl +0 -0
  25. data/spec/fixtures/set_v2.pkl +0 -0
  26. data/spec/fixtures/set_v3.pkl +0 -0
  27. data/spec/fixtures/set_v4.pkl +0 -0
  28. data/spec/fixtures/set_v5.pkl +0 -0
  29. data/spec/generate_pickles2.py +1 -0
  30. data/spec/generate_pickles3.py +1 -0
  31. data/spec/integration/load/protocol0_spec.rb +10 -0
  32. data/spec/integration/load/protocol1_spec.rb +10 -0
  33. data/spec/integration/load/protocol2_spec.rb +10 -0
  34. data/spec/integration/load/protocol3_spec.rb +10 -0
  35. data/spec/integration/load/protocol4_spec.rb +10 -0
  36. data/spec/integration/load/protocol5_spec.rb +10 -0
  37. data/spec/pickle_spec.rb +61 -0
  38. data/spec/protocol0_read_instruction_examples.rb +44 -0
  39. metadata +14 -2
@@ -0,0 +1,64 @@
1
+ require 'python/pickle/instructions/proto'
2
+ require 'python/pickle/instructions/frame'
3
+ require 'python/pickle/instructions/get'
4
+ require 'python/pickle/instructions/bin_get'
5
+ require 'python/pickle/instructions/long_bin_get'
6
+ require 'python/pickle/instructions/mark'
7
+ require 'python/pickle/instructions/pop_mark'
8
+ require 'python/pickle/instructions/dup'
9
+ require 'python/pickle/instructions/put'
10
+ require 'python/pickle/instructions/bin_put'
11
+ require 'python/pickle/instructions/pop'
12
+ require 'python/pickle/instructions/memoize'
13
+ require 'python/pickle/instructions/ext1'
14
+ require 'python/pickle/instructions/ext2'
15
+ require 'python/pickle/instructions/ext4'
16
+ require 'python/pickle/instructions/persid'
17
+ require 'python/pickle/instructions/bin_persid'
18
+ require 'python/pickle/instructions/none'
19
+ require 'python/pickle/instructions/new_true'
20
+ require 'python/pickle/instructions/new_false'
21
+ require 'python/pickle/instructions/float'
22
+ require 'python/pickle/instructions/bin_float'
23
+ require 'python/pickle/instructions/int'
24
+ require 'python/pickle/instructions/bin_int1'
25
+ require 'python/pickle/instructions/long'
26
+ require 'python/pickle/instructions/long1'
27
+ require 'python/pickle/instructions/long4'
28
+ require 'python/pickle/instructions/bin_bytes'
29
+ require 'python/pickle/instructions/short_bin_bytes'
30
+ require 'python/pickle/instructions/bin_bytes8'
31
+ require 'python/pickle/instructions/string'
32
+ require 'python/pickle/instructions/bin_string'
33
+ require 'python/pickle/instructions/short_bin_string'
34
+ require 'python/pickle/instructions/bin_unicode'
35
+ require 'python/pickle/instructions/short_bin_unicode'
36
+ require 'python/pickle/instructions/bin_unicode8'
37
+ require 'python/pickle/instructions/byte_array8'
38
+ require 'python/pickle/instructions/empty_list'
39
+ require 'python/pickle/instructions/empty_tuple'
40
+ require 'python/pickle/instructions/tuple'
41
+ require 'python/pickle/instructions/empty_dict'
42
+ require 'python/pickle/instructions/empty_set'
43
+ require 'python/pickle/instructions/frozen_set'
44
+ require 'python/pickle/instructions/append'
45
+ require 'python/pickle/instructions/appends'
46
+ require 'python/pickle/instructions/add_items'
47
+ require 'python/pickle/instructions/list'
48
+ require 'python/pickle/instructions/tuple1'
49
+ require 'python/pickle/instructions/tuple2'
50
+ require 'python/pickle/instructions/tuple3'
51
+ require 'python/pickle/instructions/dict'
52
+ require 'python/pickle/instructions/global'
53
+ require 'python/pickle/instructions/stack_global'
54
+ require 'python/pickle/instructions/inst'
55
+ require 'python/pickle/instructions/obj'
56
+ require 'python/pickle/instructions/new_obj'
57
+ require 'python/pickle/instructions/new_obj_ex'
58
+ require 'python/pickle/instructions/reduce'
59
+ require 'python/pickle/instructions/build'
60
+ require 'python/pickle/instructions/set_item'
61
+ require 'python/pickle/instructions/set_items'
62
+ require 'python/pickle/instructions/next_buffer'
63
+ require 'python/pickle/instructions/readonly_buffer'
64
+ require 'python/pickle/instructions/stop'
@@ -13,11 +13,15 @@ require 'python/pickle/instructions/list'
13
13
  require 'python/pickle/instructions/none'
14
14
  require 'python/pickle/instructions/append'
15
15
  require 'python/pickle/instructions/global'
16
+ require 'python/pickle/instructions/obj'
17
+ require 'python/pickle/instructions/inst'
16
18
  require 'python/pickle/instructions/reduce'
17
19
  require 'python/pickle/instructions/build'
18
20
  require 'python/pickle/instructions/pop'
19
21
  require 'python/pickle/instructions/pop_mark'
20
22
  require 'python/pickle/instructions/dup'
23
+ require 'python/pickle/instructions/persid'
24
+ require 'python/pickle/instructions/bin_persid'
21
25
  require 'python/pickle/instructions/stop'
22
26
  require 'python/pickle/exceptions'
23
27
 
@@ -32,32 +36,180 @@ module Python
32
36
  #
33
37
  class Protocol0 < Protocol
34
38
 
35
- # Opcodes for Pickle protocol version 0.
36
- #
37
- # @see https://github.com/python/cpython/blob/main/Lib/pickletools.py
38
- OPCODES = Set[
39
- 40, # MARK
40
- 46, # STOP
41
- 48, # POP
42
- 49, # POP_MARK
43
- 50, # DUP
44
- 70, # FLOAT
45
- 73, # INT
46
- 76, # LONG
47
- 78, # NONE
48
- 82, # REDUCE
49
- 83, # STRING
50
- 86, # UNICODE
51
- 97, # APPEND
52
- 98, # BUILD
53
- 99, # GLOBAL
54
- 100, # DICT
55
- 103, # GET
56
- 108, # LIST
57
- 112, # PUT
58
- 115, # SETITEM
59
- 116 # TUPLE
60
- ]
39
+ # The `MARK` opcode.
40
+ #
41
+ # @since 0.2.0
42
+ #
43
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L102
44
+ MARK = 40
45
+
46
+ # The `STOP` opcode.
47
+ #
48
+ # @since 0.2.0
49
+ #
50
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L103
51
+ STOP = 46
52
+
53
+ # The `POP` opcode.
54
+ #
55
+ # @since 0.2.0
56
+ #
57
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L104
58
+ POP = 48
59
+
60
+ # The `POP_MARK` opcode.
61
+ #
62
+ # @since 0.2.0
63
+ #
64
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L105
65
+ POP_MARK = 49
66
+
67
+ # The `DUP` opcode.
68
+ #
69
+ # @since 0.2.0
70
+ #
71
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L106
72
+ DUP = 50
73
+
74
+ # The `FLOAT` opcode.
75
+ #
76
+ # @since 0.2.0
77
+ #
78
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L107
79
+ FLOAT = 70
80
+
81
+ # The `INT` opcode.
82
+ #
83
+ # @since 0.2.0
84
+ #
85
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L108
86
+ INT = 73
87
+
88
+ # The `LONG` opcode.
89
+ #
90
+ # @since 0.2.0
91
+ #
92
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L111
93
+ LONG = 76
94
+
95
+ # The `NONE` opcode.
96
+ #
97
+ # @since 0.2.0
98
+ #
99
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L113
100
+ NONE = 78
101
+
102
+ # The `PERSID` opcode.
103
+ #
104
+ # @since 0.2.0
105
+ #
106
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L114
107
+ PERSID = 80
108
+
109
+ # The `BINPERSID` opcode.
110
+ #
111
+ # @since 0.2.0
112
+ #
113
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L115
114
+ BINPERSID = 81
115
+
116
+ # The `REDUCE` opcode.
117
+ #
118
+ # @since 0.2.0
119
+ #
120
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L116
121
+ REDUCE = 82
122
+
123
+ # The `STRING` opcode.
124
+ #
125
+ # @since 0.2.0
126
+ #
127
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L117
128
+ STRING = 83
129
+
130
+ # The `UNICODE` opcode.
131
+ #
132
+ # @since 0.2.0
133
+ #
134
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L120
135
+ UNICODE = 86
136
+
137
+ # The `APPEND` opcode.
138
+ #
139
+ # @since 0.2.0
140
+ #
141
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L122
142
+ APPEND = 97
143
+
144
+ # The `BUILD` opcode.
145
+ #
146
+ # @since 0.2.0
147
+ #
148
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L123
149
+ BUILD = 98
150
+
151
+ # The `GLOBAL` opcode.
152
+ #
153
+ # @since 0.2.0
154
+ #
155
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L124
156
+ GLOBAL = 99
157
+
158
+ # The `DICT` opcode.
159
+ #
160
+ # @since 0.2.0
161
+ #
162
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L125
163
+ DICT = 100
164
+
165
+ # The `GET` opcode.
166
+ #
167
+ # @since 0.2.0
168
+ #
169
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L128
170
+ GET = 103
171
+
172
+ # The `INST` opcode.
173
+ #
174
+ # @since 0.2.0
175
+ #
176
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L130
177
+ INST = 105
178
+
179
+ # The `LIST` opcode.
180
+ #
181
+ # @since 0.2.0
182
+ #
183
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L132
184
+ LIST = 108
185
+
186
+ # The `OBJ` opcode.
187
+ #
188
+ # @since 0.2.0
189
+ #
190
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L137
191
+ OBJ = 111
192
+
193
+ # The `PUT` opcode.
194
+ #
195
+ # @since 0.2.0
196
+ #
197
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L135
198
+ PUT = 112
199
+
200
+ # The `SETITEM` opcode.
201
+ #
202
+ # @since 0.2.0
203
+ #
204
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L138
205
+ SETITEM = 115
206
+
207
+ # The `TUPLE` opcode.
208
+ #
209
+ # @since 0.2.0
210
+ #
211
+ # @see https://github.com/python/cpython/blob/v2.7/Lib/pickle.py#L139
212
+ TUPLE = 116
61
213
 
62
214
  #
63
215
  # Reads an instruction from the pickle stream.
@@ -70,48 +222,31 @@ module Python
70
222
  #
71
223
  def read_instruction
72
224
  case (opcode = @io.getbyte)
73
- when 40 # MARK
74
- Instructions::MARK
75
- when 46 # STOP
76
- Instructions::STOP
77
- when 48 # POP
78
- Instructions::POP
79
- when 49 # POP_MARK
80
- Instructions::POP_MARK
81
- when 50 # DUP
82
- Instructions::DUP
83
- when 70 # FLOAT
84
- Instructions::Float.new(read_float)
85
- when 73 # INT
86
- Instructions::Int.new(read_int)
87
- when 76 # LONG
88
- Instructions::Long.new(read_long)
89
- when 78 # NONE
90
- Instructions::NONE
91
- when 82 # REDUCE
92
- Instructions::REDUCE
93
- when 83 # STRING
94
- Instructions::String.new(read_string)
95
- when 86 # UNICODE
96
- Instructions::String.new(read_unicode_string)
97
- when 97 # APPEND
98
- Instructions::APPEND
99
- when 98 # BUILD
100
- Instructions::BUILD
101
- when 99 # GLOBAL
102
- Instructions::Global.new(read_nl_string,read_nl_string)
103
- when 100 # DICT
104
- Instructions::DICT
105
- when 103 # GET
106
- Instructions::Get.new(read_int)
107
- when 108 # LIST
108
- Instructions::LIST
109
- when 112 # PUT
110
- Instructions::Put.new(read_int)
111
- when 115 # SETITEM
112
- Instructions::SETITEM
113
- when 116 # TUPLE
114
- Instructions::TUPLE
225
+ when MARK then Instructions::MARK
226
+ when STOP then Instructions::STOP
227
+ when POP then Instructions::POP
228
+ when POP_MARK then Instructions::POP_MARK
229
+ when DUP then Instructions::DUP
230
+ when FLOAT then read_float_instruction
231
+ when INT then read_int_instruction
232
+ when LONG then read_long_instruction
233
+ when NONE then Instructions::NONE
234
+ when REDUCE then Instructions::REDUCE
235
+ when STRING then read_string_instruction
236
+ when UNICODE then read_unicode_instruction
237
+ when APPEND then Instructions::APPEND
238
+ when BUILD then Instructions::BUILD
239
+ when GLOBAL then read_global_instruction
240
+ when DICT then Instructions::DICT
241
+ when GET then read_get_instruction
242
+ when LIST then Instructions::LIST
243
+ when PUT then read_put_instruction
244
+ when SETITEM then Instructions::SETITEM
245
+ when TUPLE then Instructions::TUPLE
246
+ when INST then read_inst_instruction
247
+ when OBJ then Instructions::OBJ
248
+ when PERSID then read_persid_instruction
249
+ when BINPERSID then Instructions::BINPERSID
115
250
  else
116
251
  raise(InvalidFormat,"invalid opcode (#{opcode.inspect}) for protocol 0")
117
252
  end
@@ -394,6 +529,116 @@ module Python
394
529
  raise(InvalidFormat,"unexpected end of stream while parsing a long integer: #{new_string.inspect}")
395
530
  end
396
531
 
532
+ #
533
+ # Reads a `FLOAT` instruction.
534
+ #
535
+ # @return [Instructions::Float]
536
+ #
537
+ # @since 0.2.0
538
+ #
539
+ def read_float_instruction
540
+ Instructions::Float.new(read_float)
541
+ end
542
+
543
+ #
544
+ # Reads a `INT` instruction.
545
+ #
546
+ # @return [Instructions::Int]
547
+ #
548
+ # @since 0.2.0
549
+ #
550
+ def read_int_instruction
551
+ Instructions::Int.new(read_int)
552
+ end
553
+
554
+ #
555
+ # Reads a `LONG` instruction.
556
+ #
557
+ # @return [Instructions::Long]
558
+ #
559
+ # @since 0.2.0
560
+ #
561
+ def read_long_instruction
562
+ Instructions::Long.new(read_long)
563
+ end
564
+
565
+ #
566
+ # Reads a `STRING` instruction.
567
+ #
568
+ # @return [Instructions::String]
569
+ #
570
+ # @since 0.2.0
571
+ #
572
+ def read_string_instruction
573
+ Instructions::String.new(read_string)
574
+ end
575
+
576
+ #
577
+ # Reads a `UNICODE` instruction.
578
+ #
579
+ # @return [Instructions::Unicode]
580
+ #
581
+ # @since 0.2.0
582
+ #
583
+ def read_unicode_instruction
584
+ Instructions::String.new(read_unicode_string)
585
+ end
586
+
587
+ #
588
+ # Reads a `GLOBAL` instruction.
589
+ #
590
+ # @return [Instructions::Global]
591
+ #
592
+ # @since 0.2.0
593
+ #
594
+ def read_global_instruction
595
+ Instructions::Global.new(read_nl_string,read_nl_string)
596
+ end
597
+
598
+ #
599
+ # Reads a `INST` instruction.
600
+ #
601
+ # @return [Instructions::Inst]
602
+ #
603
+ # @since 0.2.0
604
+ #
605
+ def read_inst_instruction
606
+ Instructions::Inst.new(read_nl_string,read_nl_string)
607
+ end
608
+
609
+ #
610
+ # Reads a `GET` instruction.
611
+ #
612
+ # @return [Instructions::Get]
613
+ #
614
+ # @since 0.2.0
615
+ #
616
+ def read_get_instruction
617
+ Instructions::Get.new(read_int)
618
+ end
619
+
620
+ #
621
+ # Reads a `PUT` instruction.
622
+ #
623
+ # @return [Instructions::Put]
624
+ #
625
+ # @since 0.2.0
626
+ #
627
+ def read_put_instruction
628
+ Instructions::Put.new(read_int)
629
+ end
630
+
631
+ #
632
+ # Reads a `PERSID` instruction.
633
+ #
634
+ # @return [Instructions::PersID]
635
+ #
636
+ # @since 0.2.0
637
+ #
638
+ def read_persid_instruction
639
+ Instructions::PersID.new(read_nl_string)
640
+ end
641
+
397
642
  end
398
643
  end
399
644
  end