diff options
author | Jonathan Amsterdam <jba@google.com> | 2024-02-03 11:48:50 -0500 |
---|---|---|
committer | Jonathan Amsterdam <jba@google.com> | 2024-02-06 12:43:52 +0000 |
commit | 6f44cc88f5f94253096ceed16b8e0fdb117cdd06 (patch) | |
tree | 2f29d91947611e9a6889948a843fa3edf6fe58b2 /src/archive | |
parent | 6076edc55c548878c261316f3e3294f1f73125a3 (diff) | |
download | go-6f44cc88f5f94253096ceed16b8e0fdb117cdd06.tar.gz go-6f44cc88f5f94253096ceed16b8e0fdb117cdd06.zip |
archive/zip: reduce memory held by Writer.Copy
Make a copy of the argument File's FileHeader, and pass a pointer
to the copy to CreateRaw.
Passing the pointer directly causes the entire `File` to be referenced
by the receiver. The `File` includes a reference to the `ReaderAt`
underlying the `Reader`, so all its memory, which may be the entire
contents of the archive, is prevented from being garbage-collected.
Also, explain the issue in the doc comment for CreateRaw. We
cannot change its behavior because someone may depend on the
preserving the identity of its argument pointer.
For #65499.
Change-Id: Ieb4963a0ea30539d597547d3511accbd8c6b5c5a
Reviewed-on: https://go-review.googlesource.com/c/go/+/560238
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
Diffstat (limited to 'src/archive')
-rw-r--r-- | src/archive/zip/writer.go | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/src/archive/zip/writer.go b/src/archive/zip/writer.go index e33df2431c..9e2dcff713 100644 --- a/src/archive/zip/writer.go +++ b/src/archive/zip/writer.go @@ -433,6 +433,10 @@ func writeHeader(w io.Writer, h *header) error { // [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close]. // // In contrast to [Writer.CreateHeader], the bytes passed to Writer are not compressed. +// +// CreateRaw's argument is stored in w. If the argument is a pointer to the embedded +// [FileHeader] in a [File] obtained from a [Reader] created from in-memory data, +// then w will refer to all of that memory. func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) { if err := w.prepare(fh); err != nil { return nil, err @@ -471,7 +475,10 @@ func (w *Writer) Copy(f *File) error { if err != nil { return err } - fw, err := w.CreateRaw(&f.FileHeader) + // Copy the FileHeader so w doesn't store a pointer to the data + // of f's entire archive. See #65499. + fh := f.FileHeader + fw, err := w.CreateRaw(&fh) if err != nil { return err } |