Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ var builtinAllowedSymbols = []string{
"errors.New",
// fmt.Sprintf β€” string formatting; pure function, no I/O.
"fmt.Sprintf",
// io/fs.DirEntry β€” interface type for directory entries; no side effects.
"io/fs.DirEntry",
// io/fs.FileInfo β€” interface type for file information; no side effects.
"io/fs.FileInfo",
// io/fs.ModeDir β€” file mode bit constant for directories; pure constant.
Expand Down Expand Up @@ -143,13 +141,14 @@ var permanentlyBanned = map[string]string{
"unsafe": "bypasses Go's type and memory safety guarantees",
}

// TestBuiltinImportAllowlist enforces symbol-level import restrictions on
// TestBuiltinAllowedSymbols enforces symbol-level import restrictions on
// command implementation files in interp/builtins/. builtins.go is exempt as
// the package framework. Every other file's imports and pkg.Symbol references
// must be explicitly listed in builtinAllowedSymbols.
func TestBuiltinImportAllowlist(t *testing.T) {
func TestBuiltinAllowedSymbols(t *testing.T) {
// Build lookup sets from the allowlist.
allowedSymbols := make(map[string]bool, len(builtinAllowedSymbols))
usedSymbols := make(map[string]bool, len(builtinAllowedSymbols))
allowedPackages := make(map[string]bool)
for _, entry := range builtinAllowedSymbols {
dot := strings.LastIndexByte(entry, '.')
Expand Down Expand Up @@ -267,11 +266,21 @@ func TestBuiltinImportAllowlist(t *testing.T) {
if !allowedSymbols[key] {
pos := fset.Position(sel.Pos())
t.Errorf("%s:%d: %s is not in the allowlist", rel, pos.Line, key)
} else {
usedSymbols[key] = true
}
return true
})
}
if checked == 0 {
t.Fatal("no command implementation files found in interp/builtins/ sub-packages")
}

// Verify every symbol in the allowlist is actually used by at least one
// builtin. Unused entries should be removed to keep the allowlist minimal.
for _, entry := range builtinAllowedSymbols {
if !usedSymbols[entry] {
t.Errorf("allowlist symbol %q is not used by any builtin β€” remove it from builtinAllowedSymbols", entry)
}
}
}
Loading