Skip to content

Commit 5f0de29

Browse files
authored
Protect NewFilenameUnadjuster from concurrent map writes (#1192)
1 parent 38d298c commit 5f0de29

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

pkg/result/processors/filename_unadjuster.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import (
1616

1717
type posMapper func(pos token.Position) token.Position
1818

19+
type adjustMap struct {
20+
sync.Mutex
21+
m map[string]posMapper
22+
}
23+
1924
// FilenameUnadjuster is needed because a lot of linters use fset.Position(f.Pos())
2025
// to get filename. And they return adjusted filename (e.g. *.qtpl) for an issue. We need
2126
// restore real .go filename to properly output it, parse it, etc.
@@ -27,7 +32,7 @@ type FilenameUnadjuster struct {
2732

2833
var _ Processor = &FilenameUnadjuster{}
2934

30-
func processUnadjusterPkg(m map[string]posMapper, pkg *packages.Package, log logutils.Log) {
35+
func processUnadjusterPkg(m *adjustMap, pkg *packages.Package, log logutils.Log) {
3136
fset := token.NewFileSet() // it's more memory efficient to not store all in one fset
3237

3338
for _, filename := range pkg.CompiledGoFiles {
@@ -36,7 +41,7 @@ func processUnadjusterPkg(m map[string]posMapper, pkg *packages.Package, log log
3641
}
3742
}
3843

39-
func processUnadjusterFile(filename string, m map[string]posMapper, log logutils.Log, fset *token.FileSet) {
44+
func processUnadjusterFile(filename string, m *adjustMap, log logutils.Log, fset *token.FileSet) {
4045
syntax, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
4146
if err != nil {
4247
// Error will be reported by typecheck
@@ -57,7 +62,9 @@ func processUnadjusterFile(filename string, m map[string]posMapper, log logutils
5762
return // file.go -> /caches/cgo-xxx
5863
}
5964

60-
m[adjustedFilename] = func(adjustedPos token.Position) token.Position {
65+
m.Lock()
66+
defer m.Unlock()
67+
m.m[adjustedFilename] = func(adjustedPos token.Position) token.Position {
6168
tokenFile := fset.File(syntax.Pos())
6269
if tokenFile == nil {
6370
log.Warnf("Failed to get token file for %s", adjustedFilename)
@@ -68,22 +75,23 @@ func processUnadjusterFile(filename string, m map[string]posMapper, log logutils
6875
}
6976

7077
func NewFilenameUnadjuster(pkgs []*packages.Package, log logutils.Log) *FilenameUnadjuster {
71-
m := map[string]posMapper{}
78+
m := adjustMap{m: map[string]posMapper{}}
79+
7280
startedAt := time.Now()
7381
var wg sync.WaitGroup
7482
wg.Add(len(pkgs))
7583
for _, pkg := range pkgs {
7684
go func(pkg *packages.Package) {
7785
// It's important to call func here to run GC
78-
processUnadjusterPkg(m, pkg, log)
86+
processUnadjusterPkg(&m, pkg, log)
7987
wg.Done()
8088
}(pkg)
8189
}
8290
wg.Wait()
83-
log.Infof("Pre-built %d adjustments in %s", len(m), time.Since(startedAt))
91+
log.Infof("Pre-built %d adjustments in %s", len(m.m), time.Since(startedAt))
8492

8593
return &FilenameUnadjuster{
86-
m: m,
94+
m: m.m,
8795
log: log,
8896
loggedUnadjustments: map[string]bool{},
8997
}

0 commit comments

Comments
 (0)