Skip to content

Commit

Permalink
disallow multidimensional slices and arrays (#283)
Browse files Browse the repository at this point in the history
* disallow multidimensional slices and arrays

* support bytes

* add more dimensions
  • Loading branch information
tessr authored and tac0turtle committed Sep 3, 2019
1 parent 9dc1454 commit 4bec59d
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 21 deletions.
32 changes: 32 additions & 0 deletions binary-encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,45 @@ func (cdc *Codec) encodeReflectBinary(w io.Writer, info *TypeInfo, rv reflect.Va
case reflect.Array:
if info.Type.Elem().Kind() == reflect.Uint8 {
err = cdc.encodeReflectBinaryByteArray(w, info, rv, fopts)
} else if kind := info.Type.Elem().Kind(); kind == reflect.Slice || kind == reflect.Array {
// for proto3 compatibility, we do not allow multidimensional arrays,
// unless the elements involved are bytes (e.g. [][]byte)
if info.Type.Elem().Elem().Kind() != reflect.Uint8 { // byte is an alias for uint8
elem := info.Type.Elem()
for {
if elem.Kind() == reflect.Slice || elem.Kind() == reflect.Array {
elem = elem.Elem()
continue
}
if elem.Kind() == reflect.Uint8 { // byte is an alias for uint8
break
}
err = errors.New("multidimensional arrays not allowed")
break
}
}
} else {
err = cdc.encodeReflectBinaryList(w, info, rv, fopts, bare)
}

case reflect.Slice:
if info.Type.Elem().Kind() == reflect.Uint8 {
err = cdc.encodeReflectBinaryByteSlice(w, info, rv, fopts)
} else if info.Type.Elem().Kind() == reflect.Slice || info.Type.Elem().Kind() == reflect.Array {
// for proto3 compatibility, we do not allow multidimensional slices,
// unless the elements involved are bytes (e.g. [][]byte)
elem := info.Type.Elem()
for {
if elem.Kind() == reflect.Slice || elem.Kind() == reflect.Array {
elem = elem.Elem()
continue
}
if elem.Kind() == reflect.Uint8 { // byte is an alias for uint8
break
}
err = errors.New("multidimensional slices not allowed")
break
}
} else {
err = cdc.encodeReflectBinaryList(w, info, rv, fopts, bare)
}
Expand Down
21 changes: 0 additions & 21 deletions tests/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,26 +72,6 @@ type SlicesStruct struct {
EmptySl []EmptyStruct
}

type SliceSlicesStruct struct {
Int8SlSl [][]int8
Int16SlSl [][]int16
Int32SlSl [][]int32
Int64SlSl [][]int64
VarintSlSl [][]int64 `binary:"varint"`
IntSlSl [][]int
ByteSlSl [][]byte
Uint8SlSl [][]uint8
Uint16SlSl [][]uint16
Uint32SlSl [][]uint32
Uint64SlSl [][]uint64
UvarintSlSl [][]uint64 `binary:"varint"`
UintSlSl [][]uint
StringSlSl [][]string
BytesSlSl [][][]byte
TimeSlSl [][]time.Time
EmptySlSl [][]EmptyStruct
}

type PointersStruct struct {
Int8Pt *int8
Int16Pt *int16
Expand Down Expand Up @@ -195,7 +175,6 @@ var StructTypes = []interface{}{
(*ShortArraysStruct)(nil),
(*ArraysStruct)(nil),
(*SlicesStruct)(nil),
(*SliceSlicesStruct)(nil),
(*PointersStruct)(nil),
(*PointerSlicesStruct)(nil),
(*NestedPointersStruct)(nil),
Expand Down
43 changes: 43 additions & 0 deletions tests/proto3/proto3_compat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,49 @@ func TestFixedU64Roundtrip(t *testing.T) {
assert.EqualValues(t, p3ToAm.Int64, amToP3.Int64)
}

func TestMultidimensionalSlices(t *testing.T) {
s := [][]int8{
[]int8{1, 2},
[]int8{3, 4, 5}}

_, err := cdc.MarshalBinaryBare(s)
assert.Error(t, err, "expected error: multidimensional slices are not allowed")
}

func TestMultidimensionalArrays(t *testing.T) {
arr := [2][2]int8{
[2]int8{1, 2},
[2]int8{3, 4}}

_, err := cdc.MarshalBinaryBare(arr)
assert.Error(t, err, "expected error: multidimensional arrays are not allowed")
}

func TestMultidimensionalByteArraysAndSlices(t *testing.T) {
arr := [2][2]byte{
[2]byte{1, 2},
[2]byte{3, 4}}

_, err := cdc.MarshalBinaryBare(arr)
assert.NoError(t, err, "unexpected error: multidimensional arrays are allowed, as long as they are only of bytes")

s := [][]byte{
[]byte{1, 2},
[]byte{3, 4, 5}}

_, err = cdc.MarshalBinaryBare(s)
assert.NoError(t, err, "unexpected error: multidimensional slices are allowed, as long as they are only of bytes")

s2 := [][][]byte{
[][]byte{
[]byte{1, 2},
[]byte{3, 4, 5}}}

_, err = cdc.MarshalBinaryBare(s2)
assert.NoError(t, err, "unexpected error: multidimensional slices are allowed, as long as they are only of bytes")

}

func TestProto3CompatPtrsRoundtrip(t *testing.T) {
s := p3.SomeStruct{}

Expand Down

0 comments on commit 4bec59d

Please sign in to comment.