go/loader: fix a data race
The loader was calling (*types.Checker).Files on the "unsafe" package,
a global variable. Even with zero files, this operation is not a no-op
because it sets the package's "complete" flag, leading to a data race.
(Because Unsafe.complete is already set at construction, the
race is benign, but is reported by -race nonetheless.)
Fixes golang/go#20718
Change-Id: I5a4f95be5ab4c60ea3b6c2a7fb6f1b67acbf42bc
Reviewed-on: https://go-review.googlesource.com/46071
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/go/loader/loader.go b/go/loader/loader.go
index f69a668..1cd4d6e 100644
--- a/go/loader/loader.go
+++ b/go/loader/loader.go
@@ -1009,15 +1009,19 @@
time.Since(imp.start), info.Pkg.Path(), len(files))
}
- if info.Pkg == types.Unsafe && len(files) > 0 {
- panic(`addFiles("unsafe") not permitted`)
+ // Don't call checker.Files on Unsafe, even with zero files,
+ // because it would mutate the package, which is a global.
+ if info.Pkg == types.Unsafe {
+ if len(files) > 0 {
+ panic(`"unsafe" package contains unexpected files`)
+ }
+ } else {
+ // Ignore the returned (first) error since we
+ // already collect them all in the PackageInfo.
+ info.checker.Files(files)
+ info.Files = append(info.Files, files...)
}
- // Ignore the returned (first) error since we
- // already collect them all in the PackageInfo.
- info.checker.Files(files)
- info.Files = append(info.Files, files...)
-
if imp.conf.AfterTypeCheck != nil {
imp.conf.AfterTypeCheck(info, files)
}