]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: check import path restrictions
authorRobert Griesemer <gri@golang.org>
Thu, 23 Feb 2012 07:21:56 +0000 (23:21 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 23 Feb 2012 07:21:56 +0000 (23:21 -0800)
Replaces pending CL 5674097.
Thanks to ality@pbrane.org for spearheading
the effort.

R=rsc, r
CC=golang-dev
https://golang.org/cl/5683077

src/pkg/go/parser/parser.go
src/pkg/go/parser/parser_test.go

index c1e6190448641e9c50822d66b6c6604597b0a478..a122baf087997afc8d7b2306d09b0d1491f403dc 100644 (file)
@@ -14,6 +14,9 @@ import (
        "go/ast"
        "go/scanner"
        "go/token"
+       "strconv"
+       "strings"
+       "unicode"
 )
 
 // The parser structure holds the parser's internal state.
@@ -1913,6 +1916,17 @@ func (p *parser) parseStmt() (s ast.Stmt) {
 
 type parseSpecFunction func(p *parser, doc *ast.CommentGroup, iota int) ast.Spec
 
+func isValidImport(lit string) bool {
+       const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
+       s, _ := strconv.Unquote(lit) // go/scanner returns a legal string literal
+       for _, r := range s {
+               if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
+                       return false
+               }
+       }
+       return s != ""
+}
+
 func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
        if p.trace {
                defer un(trace(p, "ImportSpec"))
@@ -1929,6 +1943,9 @@ func parseImportSpec(p *parser, doc *ast.CommentGroup, _ int) ast.Spec {
 
        var path *ast.BasicLit
        if p.tok == token.STRING {
+               if !isValidImport(p.lit) {
+                       p.error(p.pos, "invalid import path: "+p.lit)
+               }
                path = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
                p.next()
        } else {
index a3ee8525de29b931e73594c9570f3b91684e2139..da0df14741b0f2b711e7b8a8b58f514879348193 100644 (file)
@@ -5,6 +5,7 @@
 package parser
 
 import (
+       "fmt"
        "go/ast"
        "go/token"
        "os"
@@ -204,3 +205,32 @@ func TestVarScope(t *testing.T) {
                }
        }
 }
+
+var imports = map[string]bool{
+       "a":        true,
+       "a/b":      true,
+       "a.b":      true,
+       "m\x61th":  true,
+       "greek/αβ": true,
+       "":         false,
+       "\x00":     false,
+       "\x7f":     false,
+       "a!":       false,
+       "a b":      false,
+       `a\b`:      false,
+       "`a`":      false,
+       "\x80\x80": false,
+}
+
+func TestImports(t *testing.T) {
+       for path, isValid := range imports {
+               src := fmt.Sprintf("package p; import %q", path)
+               _, err := ParseFile(fset, "", src, 0)
+               switch {
+               case err != nil && isValid:
+                       t.Errorf("ParseFile(%s): got %v; expected no error", src, err)
+               case err == nil && !isValid:
+                       t.Errorf("ParseFile(%s): got no error; expected one", src)
+               }
+       }
+}