]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: check that Unicode-aware functions are not used
authorFilippo Valsorda <filippo@golang.org>
Mon, 10 May 2021 17:32:13 +0000 (19:32 +0200)
committerFilippo Valsorda <filippo@golang.org>
Tue, 11 May 2021 18:22:54 +0000 (18:22 +0000)
Change-Id: I398aff06bec95077bfff02bfb067aa949b70c184
Reviewed-on: https://go-review.googlesource.com/c/go/+/318429
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Roberto Clapis <roberto@golang.org>
Trust: Filippo Valsorda <filippo@golang.org>

src/net/http/http_test.go

index 3f1d7cee710ed2601ee616fb2d2a2f7e53826cbe..0d92fe5f964fb704dc4fa3ef1c1c2aae6d1ecd12 100644 (file)
@@ -9,9 +9,13 @@ package http
 import (
        "bytes"
        "internal/testenv"
+       "io/fs"
        "net/url"
+       "os"
        "os/exec"
        "reflect"
+       "regexp"
+       "strings"
        "testing"
 )
 
@@ -156,3 +160,61 @@ func BenchmarkCopyValues(b *testing.B) {
                b.Fatal("Benchmark wasn't run")
        }
 }
+
+var forbiddenStringsFunctions = map[string]bool{
+       // Functions that use Unicode-aware case folding.
+       "EqualFold":      true,
+       "Title":          true,
+       "ToLower":        true,
+       "ToLowerSpecial": true,
+       "ToTitle":        true,
+       "ToTitleSpecial": true,
+       "ToUpper":        true,
+       "ToUpperSpecial": true,
+
+       // Functions that use Unicode-aware spaces.
+       "Fields":    true,
+       "TrimSpace": true,
+}
+
+// TestNoUnicodeStrings checks that nothing in net/http uses the Unicode-aware
+// strings and bytes package functions. HTTP is mostly ASCII based, and doing
+// Unicode-aware case folding or space stripping can introduce vulnerabilities.
+func TestNoUnicodeStrings(t *testing.T) {
+       if !testenv.HasSrc() {
+               t.Skip("source code not available")
+       }
+
+       re := regexp.MustCompile(`(strings|bytes).([A-Za-z]+)`)
+       if err := fs.WalkDir(os.DirFS("."), ".", func(path string, d fs.DirEntry, err error) error {
+               if err != nil {
+                       t.Fatal(err)
+               }
+
+               if path == "internal/ascii" {
+                       return fs.SkipDir
+               }
+               if !strings.HasSuffix(path, ".go") ||
+                       strings.HasSuffix(path, "_test.go") ||
+                       path == "h2_bundle.go" || d.IsDir() {
+                       return nil
+               }
+
+               contents, err := os.ReadFile(path)
+               if err != nil {
+                       t.Fatal(err)
+               }
+               for lineNum, line := range strings.Split(string(contents), "\n") {
+                       for _, match := range re.FindAllStringSubmatch(line, -1) {
+                               if !forbiddenStringsFunctions[match[2]] {
+                                       continue
+                               }
+                               t.Errorf("disallowed call to %s at %s:%d", match[0], path, lineNum+1)
+                       }
+               }
+
+               return nil
+       }); err != nil {
+               t.Fatal(err)
+       }
+}