diff options
Diffstat (limited to 'src/runtime/debug')
| -rw-r--r-- | src/runtime/debug/mod.go | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/src/runtime/debug/mod.go b/src/runtime/debug/mod.go index 11f995ba75..8c6c48089b 100644 --- a/src/runtime/debug/mod.go +++ b/src/runtime/debug/mod.go @@ -7,7 +7,6 @@ package debug import ( "bytes" "fmt" - "strings" ) // exported from runtime @@ -17,11 +16,19 @@ func modinfo() string // in the running binary. The information is available only // in binaries built with module support. func ReadBuildInfo() (info *BuildInfo, ok bool) { - return readBuildInfo(modinfo()) + data := modinfo() + if len(data) < 32 { + return nil, false + } + data = data[16 : len(data)-16] + bi := &BuildInfo{} + if err := bi.UnmarshalText([]byte(data)); err != nil { + return nil, false + } + return bi, true } -// BuildInfo represents the build information read from -// the running binary. +// BuildInfo represents the build information read from a Go binary. type BuildInfo struct { Path string // The main package path Main Module // The module containing the main package @@ -71,80 +78,85 @@ func (bi *BuildInfo) MarshalText() ([]byte, error) { return buf.Bytes(), nil } -func readBuildInfo(data string) (*BuildInfo, bool) { - if len(data) < 32 { - return nil, false - } - data = data[16 : len(data)-16] +func (bi *BuildInfo) UnmarshalText(data []byte) (err error) { + *bi = BuildInfo{} + lineNum := 1 + defer func() { + if err != nil { + err = fmt.Errorf("could not parse Go build info: line %d: %w", lineNum, err) + } + }() - const ( - pathLine = "path\t" - modLine = "mod\t" - depLine = "dep\t" - repLine = "=>\t" + var ( + pathLine = []byte("path\t") + modLine = []byte("mod\t") + depLine = []byte("dep\t") + repLine = []byte("=>\t") + newline = []byte("\n") + tab = []byte("\t") ) - readEntryFirstLine := func(elem []string) (Module, bool) { + readModuleLine := func(elem [][]byte) (Module, error) { if len(elem) != 2 && len(elem) != 3 { - return Module{}, false + return Module{}, fmt.Errorf("expected 2 or 3 columns; got %d", len(elem)) } sum := "" if len(elem) == 3 { - sum = elem[2] + sum = string(elem[2]) } return Module{ - Path: elem[0], - Version: elem[1], + Path: string(elem[0]), + Version: string(elem[1]), Sum: sum, - }, true + }, nil } var ( - info = &BuildInfo{} last *Module - line string + line []byte ok bool ) - // Reverse of cmd/go/internal/modload.PackageBuildInfo + // Reverse of BuildInfo.String() for len(data) > 0 { - line, data, ok = strings.Cut(data, "\n") + line, data, ok = bytes.Cut(data, newline) if !ok { break } switch { - case strings.HasPrefix(line, pathLine): + case bytes.HasPrefix(line, pathLine): elem := line[len(pathLine):] - info.Path = elem - case strings.HasPrefix(line, modLine): - elem := strings.Split(line[len(modLine):], "\t") - last = &info.Main - *last, ok = readEntryFirstLine(elem) - if !ok { - return nil, false + bi.Path = string(elem) + case bytes.HasPrefix(line, modLine): + elem := bytes.Split(line[len(modLine):], tab) + last = &bi.Main + *last, err = readModuleLine(elem) + if err != nil { + return err } - case strings.HasPrefix(line, depLine): - elem := strings.Split(line[len(depLine):], "\t") + case bytes.HasPrefix(line, depLine): + elem := bytes.Split(line[len(depLine):], tab) last = new(Module) - info.Deps = append(info.Deps, last) - *last, ok = readEntryFirstLine(elem) - if !ok { - return nil, false + bi.Deps = append(bi.Deps, last) + *last, err = readModuleLine(elem) + if err != nil { + return err } - case strings.HasPrefix(line, repLine): - elem := strings.Split(line[len(repLine):], "\t") + case bytes.HasPrefix(line, repLine): + elem := bytes.Split(line[len(repLine):], tab) if len(elem) != 3 { - return nil, false + return fmt.Errorf("expected 3 columns for replacement; got %d", len(elem)) } if last == nil { - return nil, false + return fmt.Errorf("replacement with no module on previous line") } last.Replace = &Module{ - Path: elem[0], - Version: elem[1], - Sum: elem[2], + Path: string(elem[0]), + Version: string(elem[1]), + Sum: string(elem[2]), } last = nil } + lineNum++ } - return info, true + return nil } |
