Commit 995fce81 authored by Kirill Smelkov's avatar Kirill Smelkov

decoder: Return EOF, not panic on a proper end of stream

io.EOF handling was already there in instructions decoding loop, but it
was simply breaking out of the loop and in the end decode
unconditionally was trying to pop top element from stack, and since
stack is empty panicked. E.g. for "" input this way:

--- FAIL: TestDecode (0.00s)
panic: runtime error: index out of range [recovered]
        panic: runtime error: index out of range

goroutine 20 [running]:
testing.tRunner.func1(0xc4200765b0)
        /home/kirr/src/tools/go/go/src/testing/testing.go:624 +0x267
panic(0x5368c0, 0x603010)
        /home/kirr/src/tools/go/go/src/runtime/panic.go:489 +0x26e
github.com/kisielk/og-rek.Decoder.Decode(0xc4200ea5a0, 0x624908, 0x0, 0x0, 0xc4200e6b10, 0x52a180, 0xc4200ee308, 0x0, 0x0)
        /home/kirr/src/wendelin/neo/g.neo/src/github.com/kisielk/og-rek/ogorek.go:250 +0x4bb
github.com/kisielk/og-rek.TestDecode(0xc4200765b0)
        /home/kirr/src/wendelin/neo/g.neo/src/github.com/kisielk/og-rek/ogorek_test.go:80 +0x232f
testing.tRunner(0xc4200765b0, 0x567648)
        /home/kirr/src/tools/go/go/src/testing/testing.go:659 +0x98
created by testing.(*T).Run
        /home/kirr/src/tools/go/go/src/testing/testing.go:701 +0x2df
exit status 2

Fix it via reworking EOF handling:

- if we see EOF and no instructions was decoded so far - just return it
  to the caller

- if we see EOF in the middle of the stream - as valid pickle streams
  end with Stop opcode - it is unexpected EOF - return it as such.

A couple of tests had to be adjusted in TestDecode - as input there was
not a valid pickle - not ending with "." (which python pickle decoder
also does not decode at all).
parent 9f73742b
...@@ -121,14 +121,16 @@ func (d Decoder) Decode() (interface{}, error) { ...@@ -121,14 +121,16 @@ func (d Decoder) Decode() (interface{}, error) {
insn := 0 insn := 0
loop: loop:
for { for {
insn++
key, err := d.r.ReadByte() key, err := d.r.ReadByte()
if err == io.EOF { if err != nil {
break if err == io.EOF && insn != 0 {
} else if err != nil { err = io.ErrUnexpectedEOF
}
return nil, err return nil, err
} }
insn++
switch key { switch key {
case opMark: case opMark:
d.mark() d.mark()
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment