Skip to content

Commit 1cd6003

Browse files
committed
cmd/go: use workspace modules' go.sum files to check sums
By default, use workspace modules' go.sum files to check sums. Any missing sums will still be written to go.work.sum For golang#45713 Change-Id: I0f537602523dfec44d423c3c80c7ef396e1397b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/359478 Trust: Michael Matloob <[email protected]> Run-TryBot: Michael Matloob <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent f9dcda3 commit 1cd6003

4 files changed

Lines changed: 134 additions & 17 deletions

File tree

src/cmd/go/internal/modfetch/fetch.go

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ func RemoveAll(dir string) error {
384384
return robustio.RemoveAll(dir)
385385
}
386386

387-
var GoSumFile string // path to go.sum; set by package modload
387+
var GoSumFile string // path to go.sum; set by package modload
388+
var WorkspaceGoSumFiles []string // path to module go.sums in workspace; set by package modload
388389

389390
type modSum struct {
390391
mod module.Version
@@ -393,10 +394,11 @@ type modSum struct {
393394

394395
var goSum struct {
395396
mu sync.Mutex
396-
m map[module.Version][]string // content of go.sum file
397-
status map[modSum]modSumStatus // state of sums in m
398-
overwrite bool // if true, overwrite go.sum without incorporating its contents
399-
enabled bool // whether to use go.sum at all
397+
m map[module.Version][]string // content of go.sum file
398+
w map[string]map[module.Version][]string // sum file in workspace -> content of that sum file
399+
status map[modSum]modSumStatus // state of sums in m
400+
overwrite bool // if true, overwrite go.sum without incorporating its contents
401+
enabled bool // whether to use go.sum at all
400402
}
401403

402404
type modSumStatus struct {
@@ -417,23 +419,38 @@ func initGoSum() (bool, error) {
417419

418420
goSum.m = make(map[module.Version][]string)
419421
goSum.status = make(map[modSum]modSumStatus)
422+
goSum.w = make(map[string]map[module.Version][]string)
423+
424+
for _, f := range WorkspaceGoSumFiles {
425+
goSum.w[f] = make(map[module.Version][]string)
426+
_, err := readGoSumFile(goSum.w[f], f)
427+
if err != nil {
428+
return false, err
429+
}
430+
}
431+
432+
enabled, err := readGoSumFile(goSum.m, GoSumFile)
433+
goSum.enabled = enabled
434+
return enabled, err
435+
}
436+
437+
func readGoSumFile(dst map[module.Version][]string, file string) (bool, error) {
420438
var (
421439
data []byte
422440
err error
423441
)
424-
if actualSumFile, ok := fsys.OverlayPath(GoSumFile); ok {
442+
if actualSumFile, ok := fsys.OverlayPath(file); ok {
425443
// Don't lock go.sum if it's part of the overlay.
426444
// On Plan 9, locking requires chmod, and we don't want to modify any file
427445
// in the overlay. See #44700.
428446
data, err = os.ReadFile(actualSumFile)
429447
} else {
430-
data, err = lockedfile.Read(GoSumFile)
448+
data, err = lockedfile.Read(file)
431449
}
432450
if err != nil && !os.IsNotExist(err) {
433451
return false, err
434452
}
435-
goSum.enabled = true
436-
readGoSum(goSum.m, GoSumFile, data)
453+
readGoSum(dst, file, data)
437454

438455
return true, nil
439456
}
@@ -485,6 +502,16 @@ func HaveSum(mod module.Version) bool {
485502
if err != nil || !inited {
486503
return false
487504
}
505+
for _, goSums := range goSum.w {
506+
for _, h := range goSums[mod] {
507+
if !strings.HasPrefix(h, "h1:") {
508+
continue
509+
}
510+
if !goSum.status[modSum{mod, h}].dirty {
511+
return true
512+
}
513+
}
514+
}
488515
for _, h := range goSum.m[mod] {
489516
if !strings.HasPrefix(h, "h1:") {
490517
continue
@@ -602,15 +629,32 @@ func checkModSum(mod module.Version, h string) error {
602629
// If it finds a conflicting pair instead, it calls base.Fatalf.
603630
// goSum.mu must be locked.
604631
func haveModSumLocked(mod module.Version, h string) bool {
632+
sumFileName := "go.sum"
633+
if strings.HasSuffix(GoSumFile, "go.work.sum") {
634+
sumFileName = "go.work.sum"
635+
}
605636
for _, vh := range goSum.m[mod] {
606637
if h == vh {
607638
return true
608639
}
609640
if strings.HasPrefix(vh, "h1:") {
610-
base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\tgo.sum: %v"+goSumMismatch, mod.Path, mod.Version, h, vh)
641+
base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v"+goSumMismatch, mod.Path, mod.Version, h, sumFileName, vh)
642+
}
643+
}
644+
// Also check workspace sums.
645+
foundMatch := false
646+
// Check sums from all files in case there are conflicts between
647+
// the files.
648+
for goSumFile, goSums := range goSum.w {
649+
for _, vh := range goSums[mod] {
650+
if h == vh {
651+
foundMatch = true
652+
} else if strings.HasPrefix(vh, "h1:") {
653+
base.Fatalf("verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v"+goSumMismatch, mod.Path, mod.Version, h, goSumFile, vh)
654+
}
611655
}
612656
}
613-
return false
657+
return foundMatch
614658
}
615659

616660
// addModSumLocked adds the pair mod,h to go.sum.
@@ -749,7 +793,7 @@ Outer:
749793
goSum.m = make(map[module.Version][]string, len(goSum.m))
750794
readGoSum(goSum.m, GoSumFile, data)
751795
for ms, st := range goSum.status {
752-
if st.used {
796+
if st.used && !sumInWorkspaceModulesLocked(ms.mod) {
753797
addModSumLocked(ms.mod, ms.sum)
754798
}
755799
}
@@ -767,7 +811,7 @@ Outer:
767811
sort.Strings(list)
768812
for _, h := range list {
769813
st := goSum.status[modSum{m, h}]
770-
if !st.dirty || (st.used && keep[m]) {
814+
if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) {
771815
fmt.Fprintf(&buf, "%s %s %s\n", m.Path, m.Version, h)
772816
}
773817
}
@@ -784,6 +828,15 @@ Outer:
784828
return nil
785829
}
786830

831+
func sumInWorkspaceModulesLocked(m module.Version) bool {
832+
for _, goSums := range goSum.w {
833+
if _, ok := goSums[m]; ok {
834+
return true
835+
}
836+
}
837+
return false
838+
}
839+
787840
// TrimGoSum trims go.sum to contain only the modules needed for reproducible
788841
// builds.
789842
//

src/cmd/go/internal/modload/init.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,8 +624,10 @@ func LoadModFile(ctx context.Context) *Requirements {
624624
if err != nil {
625625
base.Fatalf("reading go.work: %v", err)
626626
}
627-
_ = TODOWorkspaces("Support falling back to individual module go.sum " +
628-
"files for sums not in the workspace sum file.")
627+
for _, modRoot := range modRoots {
628+
sumFile := strings.TrimSuffix(modFilePath(modRoot), ".mod") + ".sum"
629+
modfetch.WorkspaceGoSumFiles = append(modfetch.WorkspaceGoSumFiles, sumFile)
630+
}
629631
modfetch.GoSumFile = workFilePath + ".sum"
630632
} else if modRoots == nil {
631633
// We're in module mode, but not inside a module.

src/cmd/go/testdata/script/work_sum.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekuf
88
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
99
rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
1010
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
11-
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
12-
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
1311
-- go.work --
1412
go 1.18
1513

@@ -20,6 +18,9 @@ go 1.18
2018
module example.com/hi
2119

2220
require "rsc.io/quote" v1.5.2
21+
-- go.sum --
22+
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
23+
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
2324
-- main.go --
2425
package main
2526

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Test mismatched sums in go.sum files
2+
3+
! go run ./a
4+
cmpenv stderr want-error
5+
6+
-- want-error --
7+
verifying rsc.io/[email protected]/go.mod: checksum mismatch
8+
downloaded: h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
9+
$WORK${/}gopath${/}src${/}a${/}go.sum: h1:U1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
10+
11+
SECURITY ERROR
12+
This download does NOT match an earlier download recorded in go.sum.
13+
The bits may have been replaced on the origin server, or an attacker may
14+
have intercepted the download attempt.
15+
16+
For more information, see 'go help module-auth'.
17+
-- go.work --
18+
go 1.18
19+
20+
directory ./a
21+
directory ./b
22+
-- a/go.mod --
23+
go 1.18
24+
25+
module example.com/hi
26+
27+
require "rsc.io/quote" v1.5.2
28+
-- a/go.sum --
29+
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
30+
rsc.io/sampler v1.3.0/go.mod h1:U1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
31+
-- a/main.go --
32+
package main
33+
34+
import (
35+
"fmt"
36+
"rsc.io/quote"
37+
)
38+
39+
func main() {
40+
fmt.Println(quote.Hello())
41+
}
42+
-- b/go.mod --
43+
go 1.18
44+
45+
module example.com/hi
46+
47+
require "rsc.io/quote" v1.5.2
48+
-- b/go.sum --
49+
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
50+
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
51+
-- b/main.go --
52+
package main
53+
54+
import (
55+
"fmt"
56+
"rsc.io/quote"
57+
)
58+
59+
func main() {
60+
fmt.Println(quote.Hello())
61+
}

0 commit comments

Comments
 (0)