From b68c4a264d0658a8f7217f13ef003b9e666c3ded Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 18 Jun 2018 19:16:23 -0700 Subject: [PATCH 1/6] go fmt --- protocols.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols.go b/protocols.go index 62166ea..175c5fe 100644 --- a/protocols.go +++ b/protocols.go @@ -3,8 +3,8 @@ package multiaddr import ( "encoding/binary" "fmt" - "strings" "math/bits" + "strings" ) // Protocol is a Multiaddr protocol description structure. @@ -170,7 +170,7 @@ func ProtocolsWithString(s string) ([]Protocol, error) { // CodeToVarint converts an integer to a varint-encoded []byte func CodeToVarint(num int) []byte { - buf := make([]byte, bits.Len(uint(num))/7 + 1) + buf := make([]byte, bits.Len(uint(num))/7+1) n := binary.PutUvarint(buf, uint64(num)) return buf[:n] } From 5416c663d56292b78d14e52c9f6c6c3e5ec7539c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 18 Jun 2018 12:23:33 -0700 Subject: [PATCH 2/6] simplify variable-length argument handling Instead of having the transformers deal with variable length argument prefixes, just do this in the bytesToString/stringToBytes functions. --- codec.go | 32 +++++++++++++++++++++----------- multiaddr.go | 4 ++-- transcoders.go | 37 +++---------------------------------- 3 files changed, 26 insertions(+), 47 deletions(-) diff --git a/codec.go b/codec.go index 29573f2..2f3f085 100644 --- a/codec.go +++ b/codec.go @@ -50,6 +50,9 @@ func stringToBytes(s string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err) } + if p.Size < 0 { // varint size. + b.Write(CodeToVarint(len(a))) + } b.Write(a) sp = sp[1:] } @@ -74,11 +77,13 @@ func validateBytes(b []byte) (err error) { continue } - size, err := sizeForAddr(p, b) + n, size, err := sizeForAddr(p, b) if err != nil { return err } + b = b[n:] + if len(b) < size || size < 0 { return fmt.Errorf("invalid value for size") } @@ -109,11 +114,13 @@ func bytesToString(b []byte) (ret string, err error) { continue } - size, err := sizeForAddr(p, b) + n, size, err := sizeForAddr(p, b) if err != nil { return "", err } + b = b[n:] + if len(b) < size || size < 0 { return "", fmt.Errorf("invalid value for size") } @@ -125,6 +132,9 @@ func bytesToString(b []byte) (ret string, err error) { if err != nil { return "", err } + if p.Path && len(a) > 0 && a[0] == '/' { + a = a[1:] + } if len(a) > 0 { s += "/" + a } @@ -134,24 +144,24 @@ func bytesToString(b []byte) (ret string, err error) { return s, nil } -func sizeForAddr(p Protocol, b []byte) (int, error) { +func sizeForAddr(p Protocol, b []byte) (skip, size int, err error) { switch { case p.Size > 0: - return (p.Size / 8), nil + return 0, (p.Size / 8), nil case p.Size == 0: - return 0, nil + return 0, 0, nil case p.Path: size, n, err := ReadVarintCode(b) if err != nil { - return 0, err + return 0, 0, err } - return size + n, nil + return n, size, nil default: size, n, err := ReadVarintCode(b) if err != nil { - return 0, err + return 0, 0, err } - return size + n, nil + return n, size, nil } } @@ -168,12 +178,12 @@ func bytesSplit(b []byte) ([][]byte, error) { return nil, fmt.Errorf("no protocol with code %d", b[0]) } - size, err := sizeForAddr(p, b[n:]) + n2, size, err := sizeForAddr(p, b[n:]) if err != nil { return nil, err } - length := n + size + length := n + n2 + size ret = append(ret, b[:length]) b = b[length:] } diff --git a/multiaddr.go b/multiaddr.go index 2ab437c..098e5ed 100644 --- a/multiaddr.go +++ b/multiaddr.go @@ -86,12 +86,12 @@ func (m *multiaddr) Protocols() []Protocol { ps = append(ps, p) b = b[n:] - size, err := sizeForAddr(p, b) + n, size, err := sizeForAddr(p, b) if err != nil { panic(err) } - b = b[size:] + b = b[n+size:] } return ps } diff --git a/transcoders.go b/transcoders.go index 9b56e3e..6f586f3 100644 --- a/transcoders.go +++ b/transcoders.go @@ -3,7 +3,6 @@ package multiaddr import ( "encoding/base32" "encoding/binary" - "errors" "fmt" "net" "strconv" @@ -129,22 +128,10 @@ func p2pStB(s string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("failed to parse p2p addr: %s %s", s, err) } - size := CodeToVarint(len(m)) - b := append(size, m...) - return b, nil + return m, nil } func p2pBtS(b []byte) (string, error) { - // the address is a varint-prefixed multihash string representation - size, n, err := ReadVarintCode(b) - if err != nil { - return "", err - } - - b = b[n:] - if len(b) != size { - return "", errors.New("inconsistent lengths") - } m, err := mh.Cast(b) if err != nil { return "", err @@ -155,27 +142,9 @@ func p2pBtS(b []byte) (string, error) { var TranscoderUnix = NewTranscoderFromFunctions(unixStB, unixBtS) func unixStB(s string) ([]byte, error) { - // the address is the whole remaining string, prefixed by a varint len - size := CodeToVarint(len(s)) - b := append(size, []byte(s)...) - return b, nil + return []byte(s), nil } func unixBtS(b []byte) (string, error) { - // the address is a varint len prefixed string - size, n, err := ReadVarintCode(b) - if err != nil { - return "", err - } - - b = b[n:] - if len(b) != size { - return "", errors.New("inconsistent lengths") - } - if size == 0 { - return "", errors.New("invalid length") - } - s := string(b) - s = s[1:] // remove starting slash - return s, nil + return string(b), nil } From 1e4c6be785c595a4512ca6bbe1a846e07cd0bc57 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 18 Jun 2018 19:42:26 -0700 Subject: [PATCH 3/6] fully validate p2p addresses when decoding from bytes Otherwise, .String() can panic. --- codec.go | 5 +++++ transcoders.go | 36 ++++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/codec.go b/codec.go index 2f3f085..95a0f67 100644 --- a/codec.go +++ b/codec.go @@ -88,6 +88,11 @@ func validateBytes(b []byte) (err error) { return fmt.Errorf("invalid value for size") } + err = p.Transcoder.ValidateBytes(b[:size]) + if err != nil { + return err + } + b = b[size:] } diff --git a/transcoders.go b/transcoders.go index 6f586f3..7e31afa 100644 --- a/transcoders.go +++ b/transcoders.go @@ -14,17 +14,21 @@ import ( type Transcoder interface { StringToBytes(string) ([]byte, error) BytesToString([]byte) (string, error) + ValidateBytes([]byte) error } -func NewTranscoderFromFunctions(s2b func(string) ([]byte, error), - b2s func([]byte) (string, error)) Transcoder { - - return twrp{s2b, b2s} +func NewTranscoderFromFunctions( + s2b func(string) ([]byte, error), + b2s func([]byte) (string, error), + val func([]byte) error, +) Transcoder { + return twrp{s2b, b2s, val} } type twrp struct { strtobyte func(string) ([]byte, error) bytetostr func([]byte) (string, error) + validbyte func([]byte) error } func (t twrp) StringToBytes(s string) ([]byte, error) { @@ -34,8 +38,15 @@ func (t twrp) BytesToString(b []byte) (string, error) { return t.bytetostr(b) } -var TranscoderIP4 = NewTranscoderFromFunctions(ip4StB, ipBtS) -var TranscoderIP6 = NewTranscoderFromFunctions(ip6StB, ipBtS) +func (t twrp) ValidateBytes(b []byte) error { + if t.validbyte == nil { + return nil + } + return t.validbyte(b) +} + +var TranscoderIP4 = NewTranscoderFromFunctions(ip4StB, ipBtS, nil) +var TranscoderIP6 = NewTranscoderFromFunctions(ip6StB, ipBtS, nil) func ip4StB(s string) ([]byte, error) { i := net.ParseIP(s).To4() @@ -57,7 +68,7 @@ func ipBtS(b []byte) (string, error) { return net.IP(b).String(), nil } -var TranscoderPort = NewTranscoderFromFunctions(portStB, portBtS) +var TranscoderPort = NewTranscoderFromFunctions(portStB, portBtS, nil) func portStB(s string) ([]byte, error) { i, err := strconv.Atoi(s) @@ -77,7 +88,7 @@ func portBtS(b []byte) (string, error) { return strconv.Itoa(int(i)), nil } -var TranscoderOnion = NewTranscoderFromFunctions(onionStB, onionBtS) +var TranscoderOnion = NewTranscoderFromFunctions(onionStB, onionBtS, nil) func onionStB(s string) ([]byte, error) { addr := strings.Split(s, ":") @@ -120,7 +131,7 @@ func onionBtS(b []byte) (string, error) { return addr + ":" + strconv.Itoa(int(port)), nil } -var TranscoderP2P = NewTranscoderFromFunctions(p2pStB, p2pBtS) +var TranscoderP2P = NewTranscoderFromFunctions(p2pStB, p2pBtS, p2pVal) func p2pStB(s string) ([]byte, error) { // the address is a varint prefixed multihash string representation @@ -131,6 +142,11 @@ func p2pStB(s string) ([]byte, error) { return m, nil } +func p2pVal(b []byte) error { + _, err := mh.Cast(b) + return err +} + func p2pBtS(b []byte) (string, error) { m, err := mh.Cast(b) if err != nil { @@ -139,7 +155,7 @@ func p2pBtS(b []byte) (string, error) { return m.B58String(), nil } -var TranscoderUnix = NewTranscoderFromFunctions(unixStB, unixBtS) +var TranscoderUnix = NewTranscoderFromFunctions(unixStB, unixBtS, nil) func unixStB(s string) ([]byte, error) { return []byte(s), nil From 1e80322cf01b3189f495bc9deb3ba176aeb42e4e Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 18 Jun 2018 19:49:46 -0700 Subject: [PATCH 4/6] add test case for panic --- multiaddr_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/multiaddr_test.go b/multiaddr_test.go index 242f18b..59e50c4 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -478,3 +478,17 @@ func TestIPFSvP2P(t *testing.T) { } } } + +func TestInvalidP2PAddr(t *testing.T) { + badAddr := "a503221221c05877cbae039d70a5e600ea02c6f9f2942439285c9e344e26f8d280c850fad6" + bts, err := hex.DecodeString(badAddr) + if err != nil { + t.Fatal(err) + } + ma, err := NewMultiaddrBytes(bts) + if err == nil { + t.Error("should have failed") + // Check for panic + _ = ma.String() + } +} From 1fc094e0e0a05be67ecfafb432736fc2502cac8b Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 22 Jun 2018 14:31:41 -0700 Subject: [PATCH 5/6] explicitly throw away impossible write errors --- codec.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codec.go b/codec.go index 95a0f67..d95a0da 100644 --- a/codec.go +++ b/codec.go @@ -26,7 +26,7 @@ func stringToBytes(s string) ([]byte, error) { if p.Code == 0 { return nil, fmt.Errorf("no protocol with name %s", sp[0]) } - b.Write(CodeToVarint(p.Code)) + _, _ = b.Write(CodeToVarint(p.Code)) sp = sp[1:] if p.Size == 0 { // no length. @@ -51,7 +51,7 @@ func stringToBytes(s string) ([]byte, error) { return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err) } if p.Size < 0 { // varint size. - b.Write(CodeToVarint(len(a))) + _, _ = b.Write(CodeToVarint(len(a))) } b.Write(a) sp = sp[1:] From 2b4e098f3e0aa2c8bc960f0e4bdc3247efc3749c Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Fri, 22 Jun 2018 14:36:39 -0700 Subject: [PATCH 6/6] gx publish 1.3.0 --- .gx/lastpubver | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gx/lastpubver b/.gx/lastpubver index 10d5dee..a2e0d23 100644 --- a/.gx/lastpubver +++ b/.gx/lastpubver @@ -1 +1 @@ -1.2.7: QmUxSEGbv2nmYNnfXi7839wwQqTN3kwQeUxe8dTjZWZs7J +1.3.0: QmYmsdtJ3HsodkePE3eU3TsCaP2YvPZJ4LoXnNkDE5Tpt7 diff --git a/package.json b/package.json index f837594..6458b40 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,6 @@ "license": "MIT", "name": "go-multiaddr", "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", - "version": "1.2.7" + "version": "1.3.0" }