1// Package ogórek is a library for decoding Python's pickle format.
2//
3// ogórek is Polish for "pickle".
4package ogórek
5
6import (
7	"bufio"
8	"bytes"
9	"encoding/binary"
10	"errors"
11	"fmt"
12	"io"
13	"math"
14	"math/big"
15	"reflect"
16	"strconv"
17)
18
19// Opcodes
20const (
21	opMark           byte = '(' // push special markobject on stack
22	opStop                = '.' // every pickle ends with STOP
23	opPop                 = '0' // discard topmost stack item
24	opPopMark             = '1' // discard stack top through topmost markobject
25	opDup                 = '2' // duplicate top stack item
26	opFloat               = 'F' // push float object; decimal string argument
27	opInt                 = 'I' // push integer or bool; decimal string argument
28	opBinint              = 'J' // push four-byte signed int
29	opBinint1             = 'K' // push 1-byte unsigned int
30	opLong                = 'L' // push long; decimal string argument
31	opBinint2             = 'M' // push 2-byte unsigned int
32	opNone                = 'N' // push None
33	opPersid              = 'P' // push persistent object; id is taken from string arg
34	opBinpersid           = 'Q' //  "       "         "  ;  "  "   "     "  stack
35	opReduce              = 'R' // apply callable to argtuple, both on stack
36	opString              = 'S' // push string; NL-terminated string argument
37	opBinstring           = 'T' // push string; counted binary string argument
38	opShortBinstring      = 'U' //  "     "   ;    "      "       "      " < 256 bytes
39	opUnicode             = 'V' // push Unicode string; raw-unicode-escaped"d argument
40	opBinunicode          = 'X' //   "     "       "  ; counted UTF-8 string argument
41	opAppend              = 'a' // append stack top to list below it
42	opBuild               = 'b' // call __setstate__ or __dict__.update()
43	opGlobal              = 'c' // push self.find_class(modname, name); 2 string args
44	opDict                = 'd' // build a dict from stack items
45	opEmptyDict           = '}' // push empty dict
46	opAppends             = 'e' // extend list on stack by topmost stack slice
47	opGet                 = 'g' // push item from memo on stack; index is string arg
48	opBinget              = 'h' //   "    "    "    "   "   "  ;   "    " 1-byte arg
49	opInst                = 'i' // build & push class instance
50	opLongBinget          = 'j' // push item from memo on stack; index is 4-byte arg
51	opList                = 'l' // build list from topmost stack items
52	opEmptyList           = ']' // push empty list
53	opObj                 = 'o' // build & push class instance
54	opPut                 = 'p' // store stack top in memo; index is string arg
55	opBinput              = 'q' //   "     "    "   "   " ;   "    " 1-byte arg
56	opLongBinput          = 'r' //   "     "    "   "   " ;   "    " 4-byte arg
57	opSetitem             = 's' // add key+value pair to dict
58	opTuple               = 't' // build tuple from topmost stack items
59	opEmptyTuple          = ')' // push empty tuple
60	opSetitems            = 'u' // modify dict by adding topmost key+value pairs
61	opBinfloat            = 'G' // push float; arg is 8-byte float encoding
62
63	opTrue  = "I01\n" // not an opcode; see INT docs in pickletools.py
64	opFalse = "I00\n" // not an opcode; see INT docs in pickletools.py
65
66	// Protocol 2
67
68	opProto    = '\x80' // identify pickle protocol
69	opNewobj   = '\x81' // build object by applying cls.__new__ to argtuple
70	opExt1     = '\x82' // push object from extension registry; 1-byte index
71	opExt2     = '\x83' // ditto, but 2-byte index
72	opExt4     = '\x84' // ditto, but 4-byte index
73	opTuple1   = '\x85' // build 1-tuple from stack top
74	opTuple2   = '\x86' // build 2-tuple from two topmost stack items
75	opTuple3   = '\x87' // build 3-tuple from three topmost stack items
76	opNewtrue  = '\x88' // push True
77	opNewfalse = '\x89' // push False
78	opLong1    = '\x8a' // push long from < 256 bytes
79	opLong4    = '\x8b' // push really big long
80
81	// Protocol 4
82	opShortBinUnicode = '\x8c' // push short string; UTF-8 length < 256 bytes
83	opMemoize         = '\x94' // store top of the stack in memo
84	opFrame           = '\x95' // indicate the beginning of a new frame
85)
86
87var errNotImplemented = errors.New("unimplemented opcode")
88var ErrInvalidPickleVersion = errors.New("invalid pickle version")
89var errNoMarker = errors.New("no marker in stack")
90var errStackUnderflow = errors.New("pickle: stack underflow")
91
92type OpcodeError struct {
93	Key byte
94	Pos int
95}
96
97func (e OpcodeError) Error() string {
98	return fmt.Sprintf("Unknown opcode %d (%c) at position %d: %q", e.Key, e.Key, e.Pos, e.Key)
99}
100
101// special marker
102type mark struct{}
103
104// None is a representation of Python's None.
105type None struct{}
106
107// Tuple is a representation of Python's tuple.
108type Tuple []interface{}
109
110// Decoder is a decoder for pickle streams.
111type Decoder struct {
112	r     *bufio.Reader
113	stack []interface{}
114	memo  map[string]interface{}
115
116	// a reusable buffer that can be used by the various decoding functions
117	// functions using this should call buf.Reset to clear the old contents
118	buf bytes.Buffer
119
120	// reusable buffer for readLine
121	line  []byte
122}
123
124// NewDecoder constructs a new Decoder which will decode the pickle stream in r.
125func NewDecoder(r io.Reader) *Decoder {
126	reader := bufio.NewReader(r)
127	return &Decoder{r: reader, stack: make([]interface{}, 0), memo: make(map[string]interface{})}
128}
129
130// Decode decodes the pickle stream and returns the result or an error.
131func (d *Decoder) Decode() (interface{}, error) {
132
133	insn := 0
134loop:
135	for {
136		key, err := d.r.ReadByte()
137		if err != nil {
138			if err == io.EOF && insn != 0 {
139				err = io.ErrUnexpectedEOF
140			}
141			return nil, err
142		}
143
144		insn++
145
146		switch key {
147		case opMark:
148			d.mark()
149		case opStop:
150			break loop
151		case opPop:
152			_, err = d.pop()
153		case opPopMark:
154			d.popMark()
155		case opDup:
156			err = d.dup()
157		case opFloat:
158			err = d.loadFloat()
159		case opInt:
160			err = d.loadInt()
161		case opBinint:
162			err = d.loadBinInt()
163		case opBinint1:
164			err = d.loadBinInt1()
165		case opLong:
166			err = d.loadLong()
167		case opBinint2:
168			err = d.loadBinInt2()
169		case opNone:
170			err = d.loadNone()
171		case opPersid:
172			err = d.loadPersid()
173		case opBinpersid:
174			err = d.loadBinPersid()
175		case opReduce:
176			err = d.reduce()
177		case opString:
178			err = d.loadString()
179		case opBinstring:
180			err = d.loadBinString()
181		case opShortBinstring:
182			err = d.loadShortBinString()
183		case opUnicode:
184			err = d.loadUnicode()
185		case opBinunicode:
186			err = d.loadBinUnicode()
187		case opAppend:
188			err = d.loadAppend()
189		case opBuild:
190			err = d.build()
191		case opGlobal:
192			err = d.global()
193		case opDict:
194			err = d.loadDict()
195		case opEmptyDict:
196			err = d.loadEmptyDict()
197		case opAppends:
198			err = d.loadAppends()
199		case opGet:
200			err = d.get()
201		case opBinget:
202			err = d.binGet()
203		case opInst:
204			err = d.inst()
205		case opLong1:
206			err = d.loadLong1()
207		case opNewfalse:
208			err = d.loadBool(false)
209		case opNewtrue:
210			err = d.loadBool(true)
211		case opLongBinget:
212			err = d.longBinGet()
213		case opList:
214			err = d.loadList()
215		case opEmptyList:
216			d.push([]interface{}{})
217		case opObj:
218			err = d.obj()
219		case opPut:
220			err = d.loadPut()
221		case opBinput:
222			err = d.binPut()
223		case opLongBinput:
224			err = d.longBinPut()
225		case opSetitem:
226			err = d.loadSetItem()
227		case opTuple:
228			err = d.loadTuple()
229		case opTuple1:
230			err = d.loadTuple1()
231		case opTuple2:
232			err = d.loadTuple2()
233		case opTuple3:
234			err = d.loadTuple3()
235		case opEmptyTuple:
236			d.push(Tuple{})
237		case opSetitems:
238			err = d.loadSetItems()
239		case opBinfloat:
240			err = d.binFloat()
241		case opFrame:
242			err = d.loadFrame()
243		case opShortBinUnicode:
244			err = d.loadShortBinUnicode()
245		case opMemoize:
246			err = d.loadMemoize()
247		case opProto:
248			v, err := d.r.ReadByte()
249			if err == nil && v != 2 {
250				err = ErrInvalidPickleVersion
251			}
252
253		default:
254			return nil, OpcodeError{key, insn}
255		}
256
257		if err != nil {
258			if err == errNotImplemented {
259				return nil, OpcodeError{key, insn}
260			}
261			// EOF from individual opcode decoder is unexpected end of stream
262			if err == io.EOF {
263				err = io.ErrUnexpectedEOF
264			}
265			return nil, err
266		}
267	}
268	return d.pop()
269}
270
271// readLine reads next line from pickle stream
272// returned line is valid only till next call to readLine
273func (d *Decoder) readLine() ([]byte, error) {
274	var (
275		data     []byte
276		isPrefix = true
277		err      error
278	)
279	d.line = d.line[:0]
280	for isPrefix {
281		data, isPrefix, err = d.r.ReadLine()
282		if err != nil {
283			return d.line, err
284		}
285		d.line = append(d.line, data...)
286	}
287	return d.line, nil
288}
289
290// Push a marker
291func (d *Decoder) mark() {
292	d.push(mark{})
293}
294
295// Return the position of the topmost marker
296func (d *Decoder) marker() (int, error) {
297	m := mark{}
298	for k := len(d.stack) - 1; k >= 0; k-- {
299		if d.stack[k] == m {
300			return k, nil
301		}
302	}
303	return 0, errNoMarker
304}
305
306// Append a new value
307func (d *Decoder) push(v interface{}) {
308	d.stack = append(d.stack, v)
309}
310
311// Pop a value
312// The returned error is errStackUnderflow if decoder stack is empty
313func (d *Decoder) pop() (interface{}, error) {
314	ln := len(d.stack) - 1
315	if ln < 0 {
316		return nil, errStackUnderflow
317	}
318	v := d.stack[ln]
319	d.stack = d.stack[:ln]
320	return v, nil
321}
322
323// Pop a value (when you know for sure decoder stack is not empty)
324func (d *Decoder) xpop() interface{} {
325	v, err := d.pop()
326	if err != nil {
327		panic(err)
328	}
329	return v
330}
331
332// Discard the stack through to the topmost marker
333func (d *Decoder) popMark() error {
334	return errNotImplemented
335}
336
337// Duplicate the top stack item
338func (d *Decoder) dup() error {
339	if len(d.stack) < 1 {
340		return errStackUnderflow
341	}
342	d.stack = append(d.stack, d.stack[len(d.stack)-1])
343	return nil
344}
345
346// Push a float
347func (d *Decoder) loadFloat() error {
348	line, err := d.readLine()
349	if err != nil {
350		return err
351	}
352	v, err := strconv.ParseFloat(string(line), 64)
353	if err != nil {
354		return err
355	}
356	d.push(interface{}(v))
357	return nil
358}
359
360// Push an int
361func (d *Decoder) loadInt() error {
362	line, err := d.readLine()
363	if err != nil {
364		return err
365	}
366
367	var val interface{}
368
369	switch string(line) {
370	case opFalse[1:3]:
371		val = false
372	case opTrue[1:3]:
373		val = true
374	default:
375		i, err := strconv.ParseInt(string(line), 10, 64)
376		if err != nil {
377			return err
378		}
379		val = i
380	}
381
382	d.push(val)
383	return nil
384}
385
386// Push a four-byte signed int
387func (d *Decoder) loadBinInt() error {
388	var b [4]byte
389	_, err := io.ReadFull(d.r, b[:])
390	if err != nil {
391		return err
392	}
393	v := binary.LittleEndian.Uint32(b[:])
394	d.push(int64(v))
395	return nil
396}
397
398// Push a 1-byte unsigned int
399func (d *Decoder) loadBinInt1() error {
400	b, err := d.r.ReadByte()
401	if err != nil {
402		return err
403	}
404	d.push(int64(b))
405	return nil
406}
407
408// Push a long
409func (d *Decoder) loadLong() error {
410	line, err := d.readLine()
411	if err != nil {
412		return err
413	}
414	l := len(line)
415	if l < 1 || line[l-1] != 'L' {
416		return io.ErrUnexpectedEOF
417	}
418	v := new(big.Int)
419	_, ok := v.SetString(string(line[:l-1]), 10)
420	if !ok {
421		return fmt.Errorf("pickle: loadLong: invalid string")
422	}
423	d.push(v)
424	return nil
425}
426
427// Push a long1
428func (d *Decoder) loadLong1() error {
429	rawNum := []byte{}
430	b, err := d.r.ReadByte()
431	if err != nil {
432		return err
433	}
434	length, err := decodeLong(string(b))
435	if err != nil {
436		return err
437	}
438	for i := 0; int64(i) < length.Int64(); i++ {
439		b2, err := d.r.ReadByte()
440		if err != nil {
441			return err
442		}
443		rawNum = append(rawNum, b2)
444	}
445	decodedNum, err := decodeLong(string(rawNum))
446	d.push(decodedNum)
447	return nil
448}
449
450// Push a 2-byte unsigned int
451func (d *Decoder) loadBinInt2() error {
452	var b [2]byte
453	_, err := io.ReadFull(d.r, b[:])
454	if err != nil {
455		return err
456	}
457	v := binary.LittleEndian.Uint16(b[:])
458	d.push(int64(v))
459	return nil
460}
461
462// Push None
463func (d *Decoder) loadNone() error {
464	d.push(None{})
465	return nil
466}
467
468// Push a persistent object id
469func (d *Decoder) loadPersid() error {
470	return errNotImplemented
471}
472
473// Push a persistent object id from items on the stack
474func (d *Decoder) loadBinPersid() error {
475	return errNotImplemented
476}
477
478type Call struct {
479	Callable Class
480	Args     Tuple
481}
482
483func (d *Decoder) reduce() error {
484	if len(d.stack) < 2 {
485		return errStackUnderflow
486	}
487	xargs := d.xpop()
488	xclass := d.xpop()
489	args, ok := xargs.(Tuple)
490	if !ok {
491		return fmt.Errorf("pickle: reduce: invalid args: %T", xargs)
492	}
493	class, ok := xclass.(Class)
494	if !ok {
495		return fmt.Errorf("pickle: reduce: invalid class: %T", xclass)
496	}
497	d.stack = append(d.stack, Call{Callable: class, Args: args})
498	return nil
499}
500
501func decodeStringEscape(b []byte) string {
502	// TODO
503	return string(b)
504}
505
506// Push a string
507func (d *Decoder) loadString() error {
508	line, err := d.readLine()
509	if err != nil {
510		return err
511	}
512
513	if len(line) < 2 {
514		return io.ErrUnexpectedEOF
515	}
516
517	var delim byte
518	switch line[0] {
519	case '\'':
520		delim = '\''
521	case '"':
522		delim = '"'
523	default:
524		return fmt.Errorf("invalid string delimiter: %c", line[0])
525	}
526
527	if line[len(line)-1] != delim {
528		return io.ErrUnexpectedEOF
529	}
530
531	d.push(decodeStringEscape(line[1 : len(line)-1]))
532	return nil
533}
534
535func (d *Decoder) loadBinString() error {
536	var b [4]byte
537	_, err := io.ReadFull(d.r, b[:])
538	if err != nil {
539		return err
540	}
541	v := binary.LittleEndian.Uint32(b[:])
542
543	d.buf.Reset()
544	d.buf.Grow(int(v))
545	_, err = io.CopyN(&d.buf, d.r, int64(v))
546	if err != nil {
547		return err
548	}
549	d.push(d.buf.String())
550	return nil
551}
552
553func (d *Decoder) loadShortBinString() error {
554	b, err := d.r.ReadByte()
555	if err != nil {
556		return err
557	}
558
559	d.buf.Reset()
560	d.buf.Grow(int(b))
561	_, err = io.CopyN(&d.buf, d.r, int64(b))
562	if err != nil {
563		return err
564	}
565	d.push(d.buf.String())
566	return nil
567}
568
569func (d *Decoder) loadUnicode() error {
570	line, err := d.readLine()
571
572	if err != nil {
573		return err
574	}
575	sline := string(line)
576
577	d.buf.Reset()
578	d.buf.Grow(len(line)) // approximation
579
580	for len(sline) > 0 {
581		var r rune
582		var err error
583		for len(sline) > 0 && sline[0] == '\'' {
584			d.buf.WriteByte(sline[0])
585			sline = sline[1:]
586		}
587		if len(sline) == 0 {
588			break
589		}
590		r, _, sline, err = strconv.UnquoteChar(sline, '\'')
591		if err != nil {
592			return err
593		}
594		d.buf.WriteRune(r)
595	}
596	if len(sline) > 0 {
597		return fmt.Errorf("characters remaining after loadUnicode operation: %s", sline)
598	}
599
600	d.push(d.buf.String())
601	return nil
602}
603
604func (d *Decoder) loadBinUnicode() error {
605	var length int32
606	for i := 0; i < 4; i++ {
607		t, err := d.r.ReadByte()
608		if err != nil {
609			return err
610		}
611		length = length | (int32(t) << uint(8*i))
612	}
613	rawB := []byte{}
614	for z := 0; int32(z) < length; z++ {
615		n, err := d.r.ReadByte()
616		if err != nil {
617			return err
618		}
619		rawB = append(rawB, n)
620	}
621	d.push(string(rawB))
622	return nil
623}
624
625func (d *Decoder) loadAppend() error {
626	if len(d.stack) < 2 {
627		return errStackUnderflow
628	}
629	v := d.xpop()
630	l := d.stack[len(d.stack)-1]
631	switch l.(type) {
632	case []interface{}:
633		l := l.([]interface{})
634		d.stack[len(d.stack)-1] = append(l, v)
635	default:
636		return fmt.Errorf("pickle: loadAppend: expected a list, got %T", l)
637	}
638	return nil
639}
640
641func (d *Decoder) build() error {
642	return errNotImplemented
643}
644
645type Class struct {
646	Module, Name string
647}
648
649func (d *Decoder) global() error {
650	module, err := d.readLine()
651	if err != nil {
652		return err
653	}
654	smodule := string(module)
655	name, err := d.readLine()
656	if err != nil {
657		return err
658	}
659	sname := string(name)
660	d.stack = append(d.stack, Class{Module: smodule, Name: sname})
661	return nil
662}
663
664func (d *Decoder) loadDict() error {
665	k, err := d.marker()
666	if err != nil {
667		return err
668	}
669
670	m := make(map[interface{}]interface{}, 0)
671	items := d.stack[k+1:]
672	if len(items) % 2 != 0 {
673		return fmt.Errorf("pickle: loadDict: odd # of elements")
674	}
675	for i := 0; i < len(items); i += 2 {
676		key := items[i]
677		if !reflect.TypeOf(key).Comparable() {
678			return fmt.Errorf("pickle: loadDict: invalid key type %T", key)
679		}
680		m[key] = items[i+1]
681	}
682	d.stack = append(d.stack[:k], m)
683	return nil
684}
685
686func (d *Decoder) loadEmptyDict() error {
687	m := make(map[interface{}]interface{}, 0)
688	d.push(m)
689	return nil
690}
691
692func (d *Decoder) loadAppends() error {
693	k, err := d.marker()
694	if err != nil {
695		return err
696	}
697	if k < 1 {
698		return errStackUnderflow
699	}
700
701	l := d.stack[k-1]
702	switch l.(type) {
703	case []interface{}:
704		l := l.([]interface{})
705		for _, v := range d.stack[k+1 : len(d.stack)] {
706			l = append(l, v)
707		}
708		d.stack = append(d.stack[:k-1], l)
709	default:
710		return fmt.Errorf("pickle: loadAppends: expected a list, got %T", l)
711	}
712	return nil
713}
714
715func (d *Decoder) get() error {
716	line, err := d.readLine()
717	if err != nil {
718		return err
719	}
720	v, ok := d.memo[string(line)]
721	if !ok {
722		return fmt.Errorf("pickle: memo: key error %q", line)
723	}
724	d.push(v)
725	return nil
726}
727
728func (d *Decoder) binGet() error {
729	b, err := d.r.ReadByte()
730	if err != nil {
731		return err
732	}
733
734	v, ok := d.memo[strconv.Itoa(int(b))]
735	if !ok {
736		return fmt.Errorf("pickle: memo: key error %d", b)
737	}
738	d.push(v)
739	return nil
740}
741
742func (d *Decoder) inst() error {
743	return errNotImplemented
744}
745
746func (d *Decoder) longBinGet() error {
747	var b [4]byte
748	_, err := io.ReadFull(d.r, b[:])
749	if err != nil {
750		return err
751	}
752	v := binary.LittleEndian.Uint32(b[:])
753	vv, ok := d.memo[strconv.Itoa(int(v))]
754	if !ok {
755		return fmt.Errorf("pickle: memo: key error %d", v)
756	}
757	d.push(vv)
758	return nil
759}
760
761func (d *Decoder) loadBool(b bool) error {
762	d.push(b)
763	return nil
764}
765
766func (d *Decoder) loadList() error {
767	k, err := d.marker()
768	if err != nil {
769		return err
770	}
771
772	v := append([]interface{}{}, d.stack[k+1:]...)
773	d.stack = append(d.stack[:k], v)
774	return nil
775}
776
777func (d *Decoder) loadTuple() error {
778	k, err := d.marker()
779	if err != nil {
780		return err
781	}
782
783	v := append(Tuple{}, d.stack[k+1:]...)
784	d.stack = append(d.stack[:k], v)
785	return nil
786}
787
788func (d *Decoder) loadTuple1() error {
789	if len(d.stack) < 1 {
790		return errStackUnderflow
791	}
792	k := len(d.stack) - 1
793	v := append(Tuple{}, d.stack[k:]...)
794	d.stack = append(d.stack[:k], v)
795	return nil
796}
797
798func (d *Decoder) loadTuple2() error {
799	if len(d.stack) < 2 {
800		return errStackUnderflow
801	}
802	k := len(d.stack) - 2
803	v := append(Tuple{}, d.stack[k:]...)
804	d.stack = append(d.stack[:k], v)
805	return nil
806}
807
808func (d *Decoder) loadTuple3() error {
809	if len(d.stack) < 3 {
810		return errStackUnderflow
811	}
812	k := len(d.stack) - 3
813	v := append(Tuple{}, d.stack[k:]...)
814	d.stack = append(d.stack[:k], v)
815	return nil
816}
817
818func (d *Decoder) obj() error {
819	return errNotImplemented
820}
821
822func (d *Decoder) loadPut() error {
823	line, err := d.readLine()
824	if err != nil {
825		return err
826	}
827	if len(d.stack) < 1 {
828		return errStackUnderflow
829	}
830	d.memo[string(line)] = d.stack[len(d.stack)-1]
831	return nil
832}
833
834func (d *Decoder) binPut() error {
835	if len(d.stack) < 1 {
836		return errStackUnderflow
837	}
838	b, err := d.r.ReadByte()
839	if err != nil {
840		return err
841	}
842
843	d.memo[strconv.Itoa(int(b))] = d.stack[len(d.stack)-1]
844	return nil
845}
846
847func (d *Decoder) longBinPut() error {
848	if len(d.stack) < 1 {
849		return errStackUnderflow
850	}
851	var b [4]byte
852	_, err := io.ReadFull(d.r, b[:])
853	if err != nil {
854		return err
855	}
856	v := binary.LittleEndian.Uint32(b[:])
857	d.memo[strconv.Itoa(int(v))] = d.stack[len(d.stack)-1]
858	return nil
859}
860
861func (d *Decoder) loadSetItem() error {
862	if len(d.stack) < 3 {
863		return errStackUnderflow
864	}
865	v := d.xpop()
866	k := d.xpop()
867	m := d.stack[len(d.stack)-1]
868	switch m := m.(type) {
869	case map[interface{}]interface{}:
870		if !reflect.TypeOf(k).Comparable() {
871			return fmt.Errorf("pickle: loadSetItem: invalid key type %T", k)
872		}
873		m[k] = v
874	default:
875		return fmt.Errorf("pickle: loadSetItem: expected a map, got %T", m)
876	}
877	return nil
878}
879
880func (d *Decoder) loadSetItems() error {
881	k, err := d.marker()
882	if err != nil {
883		return err
884	}
885	if k < 1 {
886		return errStackUnderflow
887	}
888
889	l := d.stack[k-1]
890	switch m := l.(type) {
891	case map[interface{}]interface{}:
892		if (len(d.stack) - (k + 1)) % 2 != 0 {
893			return fmt.Errorf("pickle: loadSetItems: odd # of elements")
894		}
895		for i := k + 1; i < len(d.stack); i += 2 {
896			key := d.stack[i]
897			if !reflect.TypeOf(key).Comparable() {
898				return fmt.Errorf("pickle: loadSetItems: invalid key type %T", key)
899			}
900			m[d.stack[i]] = d.stack[i+1]
901		}
902		d.stack = append(d.stack[:k-1], m)
903	default:
904		return fmt.Errorf("pickle: loadSetItems: expected a map, got %T", m)
905	}
906	return nil
907}
908
909func (d *Decoder) binFloat() error {
910	var b [8]byte
911	_, err := io.ReadFull(d.r, b[:])
912	if err != nil {
913		return err
914	}
915	u := binary.BigEndian.Uint64(b[:])
916	d.stack = append(d.stack, math.Float64frombits(u))
917	return nil
918}
919
920// loadFrame discards the framing opcode+information, this information is useful to do one large read (instead of many small reads)
921// https://www.python.org/dev/peps/pep-3154/#framing
922func (d *Decoder) loadFrame() error {
923	var b [8]byte
924	_, err := io.ReadFull(d.r, b[:])
925	if err != nil {
926		return err
927	}
928	return nil
929}
930
931func (d *Decoder) loadShortBinUnicode() error {
932	b, err := d.r.ReadByte()
933	if err != nil {
934		return err
935	}
936
937	d.buf.Reset()
938	d.buf.Grow(int(b))
939	_, err = io.CopyN(&d.buf, d.r, int64(b))
940	if err != nil {
941		return err
942	}
943	d.push(d.buf.String())
944	return nil
945}
946
947func (d *Decoder) loadMemoize() error {
948	if len(d.stack) < 1 {
949		return errStackUnderflow
950	}
951	d.memo[strconv.Itoa(len(d.memo))] = d.stack[len(d.stack)-1]
952	return nil
953}
954
955// decodeLong takes a byte array of 2's compliment little-endian binary words and converts them
956// to a big integer
957func decodeLong(data string) (*big.Int, error) {
958	decoded := big.NewInt(0)
959	var negative bool
960	switch x := len(data); {
961	case x < 1:
962		return decoded, nil
963	case x > 1:
964		if data[x-1] > 127 {
965			negative = true
966		}
967		for i := x - 1; i >= 0; i-- {
968			a := big.NewInt(int64(data[i]))
969			for n := i; n > 0; n-- {
970				a = a.Lsh(a, 8)
971			}
972			decoded = decoded.Add(a, decoded)
973		}
974	default:
975		if data[0] > 127 {
976			negative = true
977		}
978		decoded = big.NewInt(int64(data[0]))
979	}
980
981	if negative {
982		// Subtract 1 from the number
983		one := big.NewInt(1)
984		decoded.Sub(decoded, one)
985
986		// Flip the bits
987		bytes := decoded.Bytes()
988		for i := 0; i < len(bytes); i++ {
989			bytes[i] = ^bytes[i]
990		}
991		decoded.SetBytes(bytes)
992
993		// Mark as negative now conversion has been completed
994		decoded.Neg(decoded)
995	}
996	return decoded, nil
997}
998