]> Sergey Matveev's repositories - btrtrc.git/blobdiff - bencode/decode.go
Attribute accepted connection to holepunching when connect message is late
[btrtrc.git] / bencode / decode.go
index 1007db906c58eeafd46b282c2348d1f509122ded..3839b849c21155cffb15132d12b310d3c3936900 100644 (file)
@@ -191,7 +191,7 @@ func (d *Decoder) checkBufferedInt() error {
        return nil
 }
 
-func (d *Decoder) parseStringLength() (uint64, error) {
+func (d *Decoder) parseStringLength() (int, error) {
        // We should have already consumed the first byte of the length into the Decoder buf.
        start := d.Offset - 1
        d.readUntil(':')
@@ -201,13 +201,13 @@ func (d *Decoder) parseStringLength() (uint64, error) {
        // Really the limit should be the uint size for the platform. But we can't pass in an allocator,
        // or limit total memory use in Go, the best we might hope to do is limit the size of a single
        // decoded value (by reading it in in-place and then operating on a view).
-       length, err := strconv.ParseUint(bytesAsString(d.buf.Bytes()), 10, 0)
+       length, err := strconv.ParseInt(bytesAsString(d.buf.Bytes()), 10, 0)
        checkForIntParseError(err, start)
        if int64(length) > d.getMaxStrLen() {
                err = fmt.Errorf("parsed string length %v exceeds limit (%v)", length, DefaultDecodeMaxStrLen)
        }
        d.buf.Reset()
-       return length, err
+       return int(length), err
 }
 
 func (d *Decoder) parseString(v reflect.Value) error {
@@ -246,13 +246,25 @@ func (d *Decoder) parseString(v reflect.Value) error {
                if v.Type().Elem().Kind() != reflect.Uint8 {
                        break
                }
-               d.buf.Grow(int(length))
+               d.buf.Grow(length)
                b := d.buf.Bytes()[:length]
                read(b)
                reflect.Copy(v, reflect.ValueOf(b))
                return nil
+       case reflect.Bool:
+               d.buf.Grow(length)
+               b := d.buf.Bytes()[:length]
+               read(b)
+               x, err := strconv.ParseBool(bytesAsString(b))
+               if err != nil {
+                       x = length != 0
+               }
+               v.SetBool(x)
+               return nil
        }
-       d.buf.Grow(int(length))
+       // Can't move this into default clause because some cases above fail through to here after
+       // additional checks.
+       d.buf.Grow(length)
        read(d.buf.Bytes()[:length])
        // I believe we return here to support "ignore_unmarshal_type_error".
        return &UnmarshalTypeError{
@@ -690,7 +702,8 @@ func (d *Decoder) parseStringInterface() string {
 
 func (d *Decoder) parseDictInterface() interface{} {
        dict := make(map[string]interface{})
-       lastKey := ""
+       var lastKey string
+       lastKeyOk := false
        for {
                start := d.Offset
                keyi, ok := d.parseValueInterface()
@@ -705,7 +718,7 @@ func (d *Decoder) parseDictInterface() interface{} {
                                What:   errors.New("non-string key in a dict"),
                        })
                }
-               if key <= lastKey {
+               if lastKeyOk && key <= lastKey {
                        d.throwSyntaxError(start, fmt.Errorf("dict keys unsorted: %q <= %q", key, lastKey))
                }
                start = d.Offset
@@ -715,6 +728,7 @@ func (d *Decoder) parseDictInterface() interface{} {
                }
 
                lastKey = key
+               lastKeyOk = true
                dict[key] = valuei
        }
        return dict