|
15 | 15 | package gosec
|
16 | 16 |
|
17 | 17 | import (
|
| 18 | + "bytes" |
| 19 | + "encoding/json" |
18 | 20 | "errors"
|
19 | 21 | "fmt"
|
20 | 22 | "go/ast"
|
21 | 23 | "go/token"
|
22 | 24 | "go/types"
|
23 | 25 | "os"
|
| 26 | + "os/exec" |
24 | 27 | "os/user"
|
25 | 28 | "path/filepath"
|
26 | 29 | "regexp"
|
@@ -493,19 +496,45 @@ func RootPath(root string) (string, error) {
|
493 | 496 | return filepath.Abs(root)
|
494 | 497 | }
|
495 | 498 |
|
496 |
| -// GoVersion returns parsed version of Go from runtime |
| 499 | +// GoVersion returns parsed version of Go mod version and fallback to runtime version if not found. |
497 | 500 | func GoVersion() (int, int, int) {
|
498 |
| - return parseGoVersion(runtime.Version()) |
| 501 | + goVersion, err := goModVersion() |
| 502 | + if err != nil { |
| 503 | + return parseGoVersion(strings.TrimPrefix(runtime.Version(), "go")) |
| 504 | + } |
| 505 | + |
| 506 | + return parseGoVersion(goVersion) |
| 507 | +} |
| 508 | + |
| 509 | +type goListOutput struct { |
| 510 | + GoVersion string `json:"GoVersion"` |
| 511 | +} |
| 512 | + |
| 513 | +func goModVersion() (string, error) { |
| 514 | + cmd := exec.Command("go", "list", "-m", "-json") |
| 515 | + |
| 516 | + raw, err := cmd.CombinedOutput() |
| 517 | + if err != nil { |
| 518 | + return "", fmt.Errorf("command go list: %w: %s", err, string(raw)) |
| 519 | + } |
| 520 | + |
| 521 | + var v goListOutput |
| 522 | + err = json.NewDecoder(bytes.NewBuffer(raw)).Decode(&v) |
| 523 | + if err != nil { |
| 524 | + return "", fmt.Errorf("unmarshaling error: %w: %s", err, string(raw)) |
| 525 | + } |
| 526 | + |
| 527 | + return v.GoVersion, nil |
499 | 528 | }
|
500 | 529 |
|
501 | 530 | // parseGoVersion parses Go version.
|
502 | 531 | // example:
|
503 |
| -// - go1.19rc2 |
504 |
| -// - go1.19beta2 |
505 |
| -// - go1.19.4 |
506 |
| -// - go1.19 |
| 532 | +// - 1.19rc2 |
| 533 | +// - 1.19beta2 |
| 534 | +// - 1.19.4 |
| 535 | +// - 1.19 |
507 | 536 | func parseGoVersion(version string) (int, int, int) {
|
508 |
| - exp := regexp.MustCompile(`go(\d+).(\d+)(?:.(\d+))?.*`) |
| 537 | + exp := regexp.MustCompile(`(\d+).(\d+)(?:.(\d+))?.*`) |
509 | 538 | parts := exp.FindStringSubmatch(version)
|
510 | 539 | if len(parts) <= 1 {
|
511 | 540 | return 0, 0, 0
|
|
0 commit comments