Merge pull request #112 from multiformats/fix/deterministic

fix: minimal varint decoding
This commit is contained in:
bigs 2019-11-06 13:36:06 -05:00 committed by GitHub
commit 64e3415480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 59 deletions

View File

@ -4,6 +4,8 @@ import (
"bytes"
"fmt"
"strings"
"github.com/multiformats/go-varint"
)
func stringToBytes(s string) ([]byte, error) {
@ -30,7 +32,7 @@ func stringToBytes(s string) ([]byte, error) {
if p.Code == 0 {
return nil, fmt.Errorf("failed to parse multiaddr %q: unknown protocol %s", s, sp[0])
}
_, _ = b.Write(CodeToVarint(p.Code))
_, _ = b.Write(p.VCode)
sp = sp[1:]
if p.Size == 0 { // no length.
@ -52,7 +54,7 @@ func stringToBytes(s string) ([]byte, error) {
return nil, fmt.Errorf("failed to parse multiaddr %q: invalid value %q for protocol %s: %s", s, sp[0], p.Name, err)
}
if p.Size < 0 { // varint size.
_, _ = b.Write(CodeToVarint(len(a)))
_, _ = b.Write(varint.ToUvarint(uint64(len(a))))
}
b.Write(a)
sp = sp[1:]

View File

@ -6,6 +6,8 @@ import (
"encoding/json"
"fmt"
"strings"
"github.com/multiformats/go-varint"
)
// Component is a single multiaddr Component.
@ -158,7 +160,7 @@ func newComponent(protocol Protocol, bvalue []byte) *Component {
size := len(bvalue)
size += len(protocol.VCode)
if protocol.Size < 0 {
size += VarintSize(len(bvalue))
size += varint.UvarintSize(uint64(len(bvalue)))
}
maddr := make([]byte, size)
var offset int

7
go.mod
View File

@ -1,5 +1,8 @@
module github.com/multiformats/go-multiaddr
require github.com/multiformats/go-multihash v0.0.8
require (
github.com/multiformats/go-multihash v0.0.8
github.com/multiformats/go-varint v0.0.1
)
go 1.12
go 1.13

2
go.sum
View File

@ -6,6 +6,8 @@ github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg=
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

View File

@ -1,44 +1,27 @@
package multiaddr
import (
"encoding/binary"
"fmt"
"math/bits"
)
"math"
// VarintSize returns the size (in bytes) of `num` encoded as a varint.
func VarintSize(num int) int {
bits := bits.Len(uint(num))
q, r := bits/7, bits%7
size := q
if r > 0 || size == 0 {
size++
}
return size
}
"github.com/multiformats/go-varint"
)
// CodeToVarint converts an integer to a varint-encoded []byte
func CodeToVarint(num int) []byte {
buf := make([]byte, VarintSize(num))
n := binary.PutUvarint(buf, uint64(num))
return buf[:n]
if num < 0 || num > math.MaxInt32 {
panic("invalid code")
}
return varint.ToUvarint(uint64(num))
}
// VarintToCode converts a varint-encoded []byte to an integer protocol code
func VarintToCode(buf []byte) int {
num, _, err := ReadVarintCode(buf)
func ReadVarintCode(b []byte) (int, int, error) {
code, n, err := varint.FromUvarint(b)
if err != nil {
panic(err)
return 0, 0, err
}
return num
}
// ReadVarintCode reads a varint code from the beginning of buf.
// returns the code, and the number of bytes read.
func ReadVarintCode(buf []byte) (int, int, error) {
num, n := binary.Uvarint(buf)
if n < 0 {
return 0, 0, fmt.Errorf("varints larger than uint64 not yet supported")
if code > math.MaxInt32 {
// we only allow 32bit codes.
return 0, 0, varint.ErrOverflow
}
return int(num), n, nil
return int(code), n, err
}

View File

@ -1,23 +0,0 @@
package multiaddr
import (
"encoding/binary"
"testing"
)
func checkVarint(t *testing.T, x int) {
buf := make([]byte, binary.MaxVarintLen64)
expected := binary.PutUvarint(buf, uint64(x))
size := VarintSize(x)
if size != expected {
t.Fatalf("expected varintsize of %d to be %d, got %d", x, expected, size)
}
}
func TestVarintSize(t *testing.T) {
max := 1 << 16
for x := 0; x < max; x++ {
checkVarint(t, x)
}
}