mirror of https://github.com/golang/go.git
go/gcexportdata: limit reader to the export data section of the archive
When given an archive, NewReader can figure out the size of the export data and there is no need to read the entire file, which includes object code for the package in addition to export data. We could make the same change in gcimporter.Import but choose not to, as the function has no users. Fixes golang/go#48954 Change-Id: I11e8e448c3133465f0e6ab01b3532da3732387af Reviewed-on: https://go-review.googlesource.com/c/tools/+/357209 Trust: Dominik Honnef <dominik@honnef.co> Run-TryBot: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
4100dac8a1
commit
baf4e38fc7
|
|
@ -50,11 +50,24 @@ func Find(importPath, srcDir string) (filename, path string) {
|
|||
// additional trailing data beyond the end of the export data.
|
||||
func NewReader(r io.Reader) (io.Reader, error) {
|
||||
buf := bufio.NewReader(r)
|
||||
_, err := gcimporter.FindExportData(buf)
|
||||
// If we ever switch to a zip-like archive format with the ToC
|
||||
// at the end, we can return the correct portion of export data,
|
||||
// but for now we must return the entire rest of the file.
|
||||
return buf, err
|
||||
_, size, err := gcimporter.FindExportData(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if size >= 0 {
|
||||
// We were given an archive and found the __.PKGDEF in it.
|
||||
// This tells us the size of the export data, and we don't
|
||||
// need to return the entire file.
|
||||
return &io.LimitedReader{
|
||||
R: buf,
|
||||
N: size,
|
||||
}, nil
|
||||
} else {
|
||||
// We were given an object file. As such, we don't know how large
|
||||
// the export data is and must return the entire file.
|
||||
return buf, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Read reads export data from in, decodes it, and returns type
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
|
||||
func readGopackHeader(r *bufio.Reader) (name string, size int64, err error) {
|
||||
// See $GOROOT/include/ar.h.
|
||||
hdr := make([]byte, 16+12+6+6+8+10+2)
|
||||
_, err = io.ReadFull(r, hdr)
|
||||
|
|
@ -28,7 +28,8 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
|
|||
fmt.Printf("header: %s", hdr)
|
||||
}
|
||||
s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
|
||||
size, err = strconv.Atoi(s)
|
||||
length, err := strconv.Atoi(s)
|
||||
size = int64(length)
|
||||
if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
|
||||
err = fmt.Errorf("invalid archive header")
|
||||
return
|
||||
|
|
@ -42,8 +43,8 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
|
|||
// file by reading from it. The reader must be positioned at the
|
||||
// start of the file before calling this function. The hdr result
|
||||
// is the string before the export data, either "$$" or "$$B".
|
||||
//
|
||||
func FindExportData(r *bufio.Reader) (hdr string, err error) {
|
||||
// The size result is the length of the export data in bytes, or -1 if not known.
|
||||
func FindExportData(r *bufio.Reader) (hdr string, size int64, err error) {
|
||||
// Read first line to make sure this is an object file.
|
||||
line, err := r.ReadSlice('\n')
|
||||
if err != nil {
|
||||
|
|
@ -54,7 +55,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
|
|||
if string(line) == "!<arch>\n" {
|
||||
// Archive file. Scan to __.PKGDEF.
|
||||
var name string
|
||||
if name, _, err = readGopackHeader(r); err != nil {
|
||||
if name, size, err = readGopackHeader(r); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -70,6 +71,7 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
|
|||
err = fmt.Errorf("can't find export data (%v)", err)
|
||||
return
|
||||
}
|
||||
size -= int64(len(line))
|
||||
}
|
||||
|
||||
// Now at __.PKGDEF in archive or still at beginning of file.
|
||||
|
|
@ -86,8 +88,12 @@ func FindExportData(r *bufio.Reader) (hdr string, err error) {
|
|||
err = fmt.Errorf("can't find export data (%v)", err)
|
||||
return
|
||||
}
|
||||
size -= int64(len(line))
|
||||
}
|
||||
hdr = string(line)
|
||||
if size < 0 {
|
||||
size = -1
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
|
|||
|
||||
var hdr string
|
||||
buf := bufio.NewReader(rc)
|
||||
if hdr, err = FindExportData(buf); err != nil {
|
||||
if hdr, _, err = FindExportData(buf); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func readExportFile(filename string) ([]byte, error) {
|
|||
defer f.Close()
|
||||
|
||||
buf := bufio.NewReader(f)
|
||||
if _, err := gcimporter.FindExportData(buf); err != nil {
|
||||
if _, _, err := gcimporter.FindExportData(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue