Fix panic unmarshalling bencode dict into unsupported type

This commit is contained in:
Matt Joiner 2021-08-12 12:16:53 +10:00
parent d03de7669b
commit a76fad32eb
2 changed files with 21 additions and 10 deletions

View File

@ -211,9 +211,9 @@ type dictField struct {
} }
// Returns specifics for parsing a dict field value. // Returns specifics for parsing a dict field value.
func getDictField(dict reflect.Type, key string) dictField { func getDictField(dict reflect.Type, key string) (_ dictField, err error) {
// get valuev as a map value or as a struct field // get valuev as a map value or as a struct field
switch dict.Kind() { switch k := dict.Kind(); k {
case reflect.Map: case reflect.Map:
return dictField{ return dictField{
Type: dict.Elem(), Type: dict.Elem(),
@ -227,9 +227,9 @@ func getDictField(dict reflect.Type, key string) dictField {
mapValue.SetMapIndex(reflect.ValueOf(key).Convert(dict.Key()), value) mapValue.SetMapIndex(reflect.ValueOf(key).Convert(dict.Key()), value)
} }
}, },
} }, nil
case reflect.Struct: case reflect.Struct:
return getStructFieldForKey(dict, key) return getStructFieldForKey(dict, key), nil
//if sf.r.PkgPath != "" { //if sf.r.PkgPath != "" {
// panic(&UnmarshalFieldError{ // panic(&UnmarshalFieldError{
// Key: key, // Key: key,
@ -238,8 +238,8 @@ func getDictField(dict reflect.Type, key string) dictField {
// }) // })
//} //}
default: default:
panic("unimplemented") err = fmt.Errorf("can't parse bencode dict items into %v", k)
return dictField{} return
} }
} }
@ -313,20 +313,22 @@ func getStructFieldForKey(struct_ reflect.Type, key string) (f dictField) {
} }
func (d *Decoder) parseDict(v reflect.Value) error { func (d *Decoder) parseDict(v reflect.Value) error {
// so, at this point 'd' byte was consumed, let's just read key/value // At this point 'd' byte was consumed, now read key/value pairs
// pairs one by one
for { for {
var keyStr string var keyStr string
keyValue := reflect.ValueOf(&keyStr).Elem() keyValue := reflect.ValueOf(&keyStr).Elem()
ok, err := d.parseValue(keyValue) ok, err := d.parseValue(keyValue)
if err != nil { if err != nil {
return fmt.Errorf("error parsing dict key: %s", err) return fmt.Errorf("error parsing dict key: %w", err)
} }
if !ok { if !ok {
return nil return nil
} }
df := getDictField(v.Type(), keyStr) df, err := getDictField(v.Type(), keyStr)
if err != nil {
return fmt.Errorf("parsing bencode dict into %v: %w", v.Type(), err)
}
// now we need to actually parse it // now we need to actually parse it
if df.Type == nil { if df.Type == nil {

View File

@ -174,3 +174,12 @@ func TestUnmarshalByteArray(t *testing.T) {
assert.NoError(t, Unmarshal([]byte("2:hi"), &ba)) assert.NoError(t, Unmarshal([]byte("2:hi"), &ba))
assert.EqualValues(t, "hi", ba[:]) assert.EqualValues(t, "hi", ba[:])
} }
func TestDecodeDictIntoUnsupported(t *testing.T) {
// Any type that a dict shouldn't be unmarshallable into.
var i int
c := qt.New(t)
err := Unmarshal([]byte("d1:a1:be"), &i)
t.Log(err)
c.Check(err, qt.Not(qt.IsNil))
}