Skip to content

Commit a93a97d

Browse files
author
Etienne Audet-Cobello
committed
internal/importpath: extract shared import path validation logic
1 parent c58d075 commit a93a97d

File tree

3 files changed

+67
-16
lines changed

3 files changed

+67
-16
lines changed

src/cmd/go/internal/modindex/build_read.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ import (
1717
"go/parser"
1818
"go/scanner"
1919
"go/token"
20+
"internal/importpath"
2021
"io"
2122
"strconv"
2223
"strings"
23-
"unicode"
2424
"unicode/utf8"
2525
)
2626

@@ -325,7 +325,7 @@ func readGoInfo(f io.Reader, info *fileInfo) error {
325325
if err != nil {
326326
return fmt.Errorf("parser returned invalid quoted string: <%s>", quoted)
327327
}
328-
if !isValidImport(path) {
328+
if !(importpath.IsValidImport(path)) {
329329
// The parser used to return a parse error for invalid import paths, but
330330
// no longer does, so check for and create the error here instead.
331331
info.parseErr = scanner.Error{Pos: info.fset.Position(spec.Pos()), Msg: "invalid import path: " + path}
@@ -389,20 +389,6 @@ func readGoInfo(f io.Reader, info *fileInfo) error {
389389
return nil
390390
}
391391

392-
// isValidImport checks if the import is a valid import using the more strict
393-
// checks allowed by the implementation restriction in https://go.dev/ref/spec#Import_declarations.
394-
// It was ported from the function of the same name that was removed from the
395-
// parser in CL 424855, when the parser stopped doing these checks.
396-
func isValidImport(s string) bool {
397-
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
398-
for _, r := range s {
399-
if !unicode.IsGraphic(r) || unicode.IsSpace(r) || strings.ContainsRune(illegalChars, r) {
400-
return false
401-
}
402-
}
403-
return s != ""
404-
}
405-
406392
// parseGoEmbed parses a "//go:embed" to extract the glob patterns.
407393
// It accepts unquoted space-separated patterns as well as double-quoted and back-quoted Go strings.
408394
// This must match the behavior of cmd/compile/internal/noder.go.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package importpath
6+
7+
import (
8+
"strings"
9+
"unicode"
10+
)
11+
12+
const illegalChars = `!"#$%&'()*,:;<=>?[\]^{|}` + "`\uFFFD"
13+
14+
func isValidImportPathChar(r rune) bool {
15+
return unicode.IsGraphic(r) && !unicode.IsSpace(r) && !strings.ContainsRune(illegalChars, r)
16+
}
17+
18+
// IsValidImport checks if the import is a valid import using the more strict
19+
// checks allowed by the implementation restriction in https://go.dev/ref/spec#Import_declarations.
20+
// This logic was previously duplicated across several packages.
21+
func IsValidImport(s string) bool {
22+
for _, r := range s {
23+
if !isValidImportPathChar(r) {
24+
return false
25+
}
26+
}
27+
return s != ""
28+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package importpath
6+
7+
import (
8+
"testing"
9+
)
10+
11+
func TestImportPath(t *testing.T) {
12+
tests := []string{
13+
"net",
14+
"net/http",
15+
"a/b/c",
16+
}
17+
for _, tc := range tests {
18+
if !IsValidImport(tc) {
19+
t.Errorf("expected %q to be valid import path", tc)
20+
}
21+
}
22+
}
23+
24+
func TestImportPathInvalid(t *testing.T) {
25+
tests := []string{
26+
"",
27+
"foo bar",
28+
"\uFFFD",
29+
"hello!",
30+
"世界",
31+
}
32+
for _, tc := range tests {
33+
if IsValidImport(tc) {
34+
t.Errorf("expected %q to be invalid import path", tc)
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)