From 7b7e35d3391eb31c04803f8a0f4574d16455b195 Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Sun, 17 Jul 2016 21:41:20 +0000 Subject: [PATCH] lib/protocol: Hello message length is an int16 It used to be an int32, but that's unnecessary and the spec now says int16. Also relaxes the size requirement to that which fits in a signed int16 instead of limiting to 1024 bytes, to allow for future growth. As reported in https://forum.syncthing.net/t/difference-between-documented-and-implemented-protocol/7798 GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/3406 --- lib/protocol/hello.go | 24 +++++++++++++++++------- lib/protocol/hello_test.go | 4 ++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/protocol/hello.go b/lib/protocol/hello.go index 8284a5179..a8a95bf00 100644 --- a/lib/protocol/hello.go +++ b/lib/protocol/hello.go @@ -56,16 +56,19 @@ func IsVersionMismatch(err error) bool { } func readHello(c io.Reader) (HelloResult, error) { - header := make([]byte, 8) + header := make([]byte, 4) if _, err := io.ReadFull(c, header); err != nil { return HelloResult{}, err } - switch binary.BigEndian.Uint32(header[:4]) { + switch binary.BigEndian.Uint32(header) { case HelloMessageMagic: // This is a v0.14 Hello message in proto format - msgSize := binary.BigEndian.Uint32(header[4:]) - if msgSize > 1024 { + if _, err := io.ReadFull(c, header[:2]); err != nil { + return HelloResult{}, err + } + msgSize := binary.BigEndian.Uint16(header[:2]) + if msgSize > 32767 { return HelloResult{}, fmt.Errorf("hello message too big") } buf := make([]byte, msgSize) @@ -86,7 +89,10 @@ func readHello(c io.Reader) (HelloResult, error) { case Version13HelloMagic: // This is a v0.13 Hello message in XDR format - msgSize := binary.BigEndian.Uint32(header[4:]) + if _, err := io.ReadFull(c, header[:4]); err != nil { + return HelloResult{}, err + } + msgSize := binary.BigEndian.Uint32(header[:4]) if msgSize > 1024 { return HelloResult{}, fmt.Errorf("hello message too big") } @@ -120,10 +126,14 @@ func writeHello(c io.Writer, h HelloIntf) error { if err != nil { return err } + if len(msg) > 32767 { + // The header length must be a positive signed int16 + panic("bug: attempting to serialize too large hello message") + } - header := make([]byte, 8) + header := make([]byte, 6) binary.BigEndian.PutUint32(header[:4], h.Magic()) - binary.BigEndian.PutUint32(header[4:], uint32(len(msg))) + binary.BigEndian.PutUint16(header[4:], uint16(len(msg))) _, err = c.Write(append(header, msg...)) return err diff --git a/lib/protocol/hello_test.go b/lib/protocol/hello_test.go index 764b5d5ea..bda51693d 100644 --- a/lib/protocol/hello_test.go +++ b/lib/protocol/hello_test.go @@ -26,9 +26,9 @@ func TestVersion14Hello(t *testing.T) { t.Fatal(err) } - hdrBuf := make([]byte, 8) + hdrBuf := make([]byte, 6) binary.BigEndian.PutUint32(hdrBuf, HelloMessageMagic) - binary.BigEndian.PutUint32(hdrBuf[4:], uint32(len(msgBuf))) + binary.BigEndian.PutUint16(hdrBuf[4:], uint16(len(msgBuf))) outBuf := new(bytes.Buffer) outBuf.Write(hdrBuf)