]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/modfetch: avoid leaking a lockedfile.File in case of write errors
authoralex.schade <39062967+aschade92@users.noreply.github.com>
Tue, 15 Feb 2022 15:35:03 +0000 (15:35 +0000)
committerBryan Mills <bcmills@google.com>
Tue, 15 Feb 2022 21:18:59 +0000 (21:18 +0000)
The go modules download command has a method called hashZip which checks the
hash of a zipped directory versus an expected value, and then writes it out
to a file. In the event that the write operation is not successful, we do
not close the file, leading to it being leaked. This could happen if the
user runs out of disk space, causing the underlying OS write command to
return an error. Ultimately, this led to a panic in lockfile.OpenFile which
was invoked from a finalizer garbage collecting the leaked file. The result
was a stack trace that didn't show the call stack from where the write
operation actually failed.

Fixes #50858

Change-Id: I4a24d2ab13dc903d623bbf8252b37bb9d724b8de
GitHub-Last-Rev: 354ef1d29ed9d9bb2d9bfe4b73306c550aab07fd
GitHub-Pull-Request: golang/go#51058
Reviewed-on: https://go-review.googlesource.com/c/go/+/383915
Trust: Cherry Mui <cherryyz@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

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

index f5423b48ad3471969766fca883394313835631ae..21d5f54688fe7f465ba6da1330212b9f2c23eff2 100644 (file)
@@ -319,7 +319,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
 //
 // If the hash does not match go.sum (or the sumdb if enabled), hashZip returns
 // an error and does not write ziphashfile.
-func hashZip(mod module.Version, zipfile, ziphashfile string) error {
+func hashZip(mod module.Version, zipfile, ziphashfile string) (err error) {
        hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash)
        if err != nil {
                return err
@@ -331,16 +331,17 @@ func hashZip(mod module.Version, zipfile, ziphashfile string) error {
        if err != nil {
                return err
        }
+       defer func() {
+               if closeErr := hf.Close(); err == nil && closeErr != nil {
+                       err = closeErr
+               }
+       }()
        if err := hf.Truncate(int64(len(hash))); err != nil {
                return err
        }
        if _, err := hf.WriteAt([]byte(hash), 0); err != nil {
                return err
        }
-       if err := hf.Close(); err != nil {
-               return err
-       }
-
        return nil
 }