]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Fix panic unmarshalling bencode dict into unsupported type v1.30.1
authorMatt Joiner <anacrolix@gmail.com>
Thu, 12 Aug 2021 02:16:53 +0000 (12:16 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Thu, 12 Aug 2021 02:16:53 +0000 (12:16 +1000)
bencode/decode.go
bencode/decode_test.go

index 43bb9ce69493cae2a90ee6eadcb944ca2b4f8328..f8ec82955a40ee4d1d9c0955fe19f45d1be2af25 100644 (file)
@@ -211,9 +211,9 @@ type dictField struct {
 }
 
 // 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
-       switch dict.Kind() {
+       switch k := dict.Kind(); k {
        case reflect.Map:
                return dictField{
                        Type: dict.Elem(),
@@ -227,9 +227,9 @@ func getDictField(dict reflect.Type, key string) dictField {
                                        mapValue.SetMapIndex(reflect.ValueOf(key).Convert(dict.Key()), value)
                                }
                        },
-               }
+               }, nil
        case reflect.Struct:
-               return getStructFieldForKey(dict, key)
+               return getStructFieldForKey(dict, key), nil
                //if sf.r.PkgPath != "" {
                //      panic(&UnmarshalFieldError{
                //              Key:   key,
@@ -238,8 +238,8 @@ func getDictField(dict reflect.Type, key string) dictField {
                //      })
                //}
        default:
-               panic("unimplemented")
-               return dictField{}
+               err = fmt.Errorf("can't parse bencode dict items into %v", k)
+               return
        }
 }
 
@@ -313,20 +313,22 @@ func getStructFieldForKey(struct_ reflect.Type, key string) (f dictField) {
 }
 
 func (d *Decoder) parseDict(v reflect.Value) error {
-       // so, at this point 'd' byte was consumed, let's just read key/value
-       // pairs one by one
+       // At this point 'd' byte was consumed, now read key/value pairs
        for {
                var keyStr string
                keyValue := reflect.ValueOf(&keyStr).Elem()
                ok, err := d.parseValue(keyValue)
                if err != nil {
-                       return fmt.Errorf("error parsing dict key: %s", err)
+                       return fmt.Errorf("error parsing dict key: %w", err)
                }
                if !ok {
                        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
                if df.Type == nil {
index 056a399a43ed1211151f3695f58e79d66e780ba1..dc610daf4f8d646dff04f1c32b6a5ef45571af63 100644 (file)
@@ -174,3 +174,12 @@ func TestUnmarshalByteArray(t *testing.T) {
        assert.NoError(t, Unmarshal([]byte("2: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))
+}