Skip to content

Commit

Permalink
fix: handle short read errors on arrays and maps (#379)
Browse files Browse the repository at this point in the history
  • Loading branch information
nrwiersma authored Apr 21, 2024
1 parent b43fe48 commit f138d7f
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 5 deletions.
4 changes: 2 additions & 2 deletions codec_array.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ func (d *arrayDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
for i := start; i < size; i++ {
elemPtr := sliceType.UnsafeGetIndex(ptr, i)
d.decoder.Decode(elemPtr, r)
if r.Error != nil && !errors.Is(r.Error, io.EOF) {
r.Error = fmt.Errorf("%s: %w", d.typ.String(), r.Error)
if r.Error != nil {
r.Error = fmt.Errorf("reading %s: %w", d.typ.String(), r.Error)
return
}
}
Expand Down
4 changes: 4 additions & 0 deletions codec_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ func (d *mapDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
keyPtr := reflect2.PtrOf(r.ReadString())
elemPtr := d.elemType.UnsafeNew()
d.decoder.Decode(elemPtr, r)
if r.Error != nil {
r.Error = fmt.Errorf("reading map[string]%s: %w", d.elemType.String(), r.Error)
return
}

d.mapType.UnsafeSetIndex(ptr, keyPtr, elemPtr)
}
Expand Down
5 changes: 2 additions & 3 deletions decoder.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package avro

import (
"errors"
"io"
)

Expand Down Expand Up @@ -36,10 +35,10 @@ func (d *Decoder) Decode(obj any) error {

d.r.ReadVal(d.s, obj)

if errors.Is(d.r.Error, io.EOF) {
//nolint:errorlint // Only direct EOF errors should be discarded.
if d.r.Error == io.EOF {
return nil
}

return d.r.Error
}

Expand Down
13 changes: 13 additions & 0 deletions decoder_array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ func TestDecoder_ArraySlice(t *testing.T) {
assert.Equal(t, []int{27, 28}, got)
}

func TestDecoder_ArraySliceShortRead(t *testing.T) {
defer ConfigTeardown()

data := []byte{0x04}
schema := `{"type":"array", "items": "int"}`
dec, _ := avro.NewDecoder(schema, bytes.NewReader(data))

var got []int
err := dec.Decode(&got)

assert.Error(t, err)
}

func TestDecoder_ArraySliceOfStruct(t *testing.T) {
defer ConfigTeardown()

Expand Down
13 changes: 13 additions & 0 deletions decoder_map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ func TestDecoder_MapMap(t *testing.T) {
assert.Equal(t, map[string]string{"foo": "foo"}, got)
}

func TestDecoder_MapMapShortRead(t *testing.T) {
defer ConfigTeardown()

data := []byte{0x02, 0x06, 0x66, 0x6F, 0x6F, 0x06, 0x06}
schema := `{"type":"map", "values": "string"}`
dec, _ := avro.NewDecoder(schema, bytes.NewReader(data))

var got map[string]string
err := dec.Decode(&got)

assert.Error(t, err)
}

func TestDecoder_MapMapOfStruct(t *testing.T) {
defer ConfigTeardown()

Expand Down

0 comments on commit f138d7f

Please sign in to comment.