]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Add fuzzing for webseed path escaping
authorMatt Joiner <anacrolix@gmail.com>
Sun, 25 Dec 2022 07:20:23 +0000 (18:20 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Sun, 25 Dec 2022 07:20:23 +0000 (18:20 +1100)
webseed/request_test.go

index 6fd033bb4642e219c8935349ebe223dff233b36a..af3071f3fd4a61f930a94f53027ff17e88ab3a42 100644 (file)
@@ -10,21 +10,51 @@ import (
 func TestDefaultPathEscaper(t *testing.T) {
        c := qt.New(t)
        test := func(unescaped string, parts ...string) {
-               escaped := defaultPathEscaper(parts)
-               pathUnescaped, err := url.PathUnescape(escaped)
-               c.Assert(err, qt.IsNil)
-               c.Assert(pathUnescaped, qt.Equals, unescaped)
-               queryUnescaped, err := url.QueryUnescape(escaped)
-               c.Assert(err, qt.IsNil)
-               c.Assert(queryUnescaped, qt.Equals, unescaped)
+               assertPartsUnescape(c, unescaped, parts...)
        }
-       test("a_b-c/d + e.f", "a_b-c", "d + e.f")
-       test("a_1-b_c2/d 3. (e, f).g", "a_1-b_c2", "d 3. (e, f).g")
-       test("a_b-c/d + e.f", "a_b-c", "d + e.f")
-       test("a_1-b_c2/d 3. (e, f).g", "a_1-b_c2", "d 3. (e, f).g")
-       test("war/and/peace", "war", "and", "peace")
-       test("hello/world", "hello", "world")
-       test(`ノ┬─┬ノ ︵ ( \o°o)\`, `ノ┬─┬ノ ︵ ( \o°o)\`)
-       test(`%aa + %bb/Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`,
-               `%aa + %bb`, `Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`)
+       for _, tc := range defaultPathEscapeTestCases {
+               test(tc.escaped, tc.parts...)
+       }
+}
+
+// So we can manually check, and use these to seed fuzzing.
+var defaultPathEscapeTestCases = []struct {
+       escaped string
+       parts   []string
+}{
+       {"/", []string{"", ""}},
+       {"a_b-c/d + e.f", []string{"a_b-c", "d + e.f"}},
+       {"a_1-b_c2/d 3. (e, f).g", []string{"a_1-b_c2", "d 3. (e, f).g"}},
+       {"a_b-c/d + e.f", []string{"a_b-c", "d + e.f"}},
+       {"a_1-b_c2/d 3. (e, f).g", []string{"a_1-b_c2", "d 3. (e, f).g"}},
+       {"war/and/peace", []string{"war", "and", "peace"}},
+       {"he//o#world/world", []string{"he//o#world", "world"}},
+       {`ノ┬─┬ノ ︵ ( \o°o)\`, []string{`ノ┬─┬ノ ︵ ( \o°o)\`}},
+       {
+               `%aa + %bb/Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`,
+               []string{`%aa + %bb`, `Parsi Tv - سرقت و باز کردن در ماشین در کم‌تر از ۳ ثانیه + فیلم.webm`},
+       },
+}
+
+func assertPartsUnescape(c *qt.C, unescaped string, parts ...string) {
+       escaped := defaultPathEscaper(parts)
+       pathUnescaped, err := url.PathUnescape(escaped)
+       c.Assert(err, qt.IsNil)
+       c.Assert(pathUnescaped, qt.Equals, unescaped)
+       queryUnescaped, err := url.QueryUnescape(escaped)
+       c.Assert(err, qt.IsNil)
+       c.Assert(queryUnescaped, qt.Equals, unescaped)
+}
+
+func FuzzDefaultPathEscaper(f *testing.F) {
+       for _, tc := range defaultPathEscapeTestCases {
+               if len(tc.parts) == 2 {
+                       f.Add(tc.parts[0], tc.parts[1])
+               }
+       }
+       // I think a single separator is enough to test special handling around /. Also fuzzing doesn't
+       // let us take []string as an input.
+       f.Fuzz(func(t *testing.T, first, second string) {
+               assertPartsUnescape(qt.New(t), first+"/"+second, first, second)
+       })
 }