From: Matt Joiner <anacrolix@gmail.com>
Date: Fri, 10 Dec 2021 03:05:00 +0000 (+1100)
Subject: bencode: Enforce dict key ordering
X-Git-Tag: v1.39.0~12
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=8764456d23c767f1ae0c9f72087d56d38af32d07;p=btrtrc.git

bencode: Enforce dict key ordering

Fix bencode dict key ordering in HTTP tracker test
---

diff --git a/bencode/decode.go b/bencode/decode.go
index 31ce157f..90397854 100644
--- a/bencode/decode.go
+++ b/bencode/decode.go
@@ -652,7 +652,9 @@ func (d *Decoder) parseStringInterface() string {
 
 func (d *Decoder) parseDictInterface() interface{} {
 	dict := make(map[string]interface{})
+	lastKey := ""
 	for {
+		start := d.Offset
 		keyi, ok := d.parseValueInterface()
 		if !ok {
 			break
@@ -665,12 +667,16 @@ func (d *Decoder) parseDictInterface() interface{} {
 				What:   errors.New("non-string key in a dict"),
 			})
 		}
-
+		if key <= lastKey {
+			d.throwSyntaxError(start, fmt.Errorf("dict keys unsorted: %q <= %q", key, lastKey))
+		}
+		start = d.Offset
 		valuei, ok := d.parseValueInterface()
 		if !ok {
-			break
+			d.throwSyntaxError(start, fmt.Errorf("dict elem missing value [key=%v]", key))
 		}
 
+		lastKey = key
 		dict[key] = valuei
 	}
 	return dict
diff --git a/bencode/decode_test.go b/bencode/decode_test.go
index 60541e86..461b3690 100644
--- a/bencode/decode_test.go
+++ b/bencode/decode_test.go
@@ -33,8 +33,8 @@ var random_decode_tests = []random_decode_test{
 		ret, _ := big.NewInt(-1).SetString("604919719469385652980544193299329427705624352086", 10)
 		return ret
 	}()},
-	{"d1:rd6:\xd4/\xe2F\x00\x01e1:t3:\x9a\x87\x011:v4:TR%=1:y1:re", map[string]interface{}{
-		"r": map[string]interface{}{},
+	{"d1:rd6:\xd4/\xe2F\x00\x01i42ee1:t3:\x9a\x87\x011:v4:TR%=1:y1:re", map[string]interface{}{
+		"r": map[string]interface{}{"\xd4/\xe2F\x00\x01": int64(42)},
 		"t": "\x9a\x87\x01",
 		"v": "TR%=",
 		"y": "r",
diff --git a/bencode/testdata/fuzz/FuzzInterfaceRoundTrip/b83176c6cec6b92f5c66774ae105efbc87c9aee44b9a55dba7f1789d8d862f45 b/bencode/testdata/fuzz/FuzzInterfaceRoundTrip/b83176c6cec6b92f5c66774ae105efbc87c9aee44b9a55dba7f1789d8d862f45
new file mode 100644
index 00000000..60cc5540
--- /dev/null
+++ b/bencode/testdata/fuzz/FuzzInterfaceRoundTrip/b83176c6cec6b92f5c66774ae105efbc87c9aee44b9a55dba7f1789d8d862f45
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("d3:A005:000003:000i0ee")
diff --git a/tracker/http/http_test.go b/tracker/http/http_test.go
index fce77c05..908b1412 100644
--- a/tracker/http/http_test.go
+++ b/tracker/http/http_test.go
@@ -16,7 +16,7 @@ func TestUnmarshalHTTPResponsePeerDicts(t *testing.T) {
 	require.NoError(t, bencode.Unmarshal(
 		[]byte("d5:peersl"+
 			"d2:ip7:1.2.3.47:peer id20:thisisthe20bytepeeri4:porti9999ee"+
-			"d7:peer id20:thisisthe20bytepeeri2:ip39:2001:0db8:85a3:0000:0000:8a2e:0370:73344:porti9998ee"+
+			"d2:ip39:2001:0db8:85a3:0000:0000:8a2e:0370:73347:peer id20:thisisthe20bytepeeri4:porti9998ee"+
 			"e"+
 			"6:peers618:123412341234123456"+
 			"e"),