Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changelog entry, panic less often, reject newer Go versions, document init order caveat #835

Merged
merged 5 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## [v0.12.1] - 2024-02-18

This bugfix release fixes a regression in v0.12.0 that broke `x/sys/unix`.
See #830.

## [v0.12.0] - 2024-02-10

This release continues support for Go 1.21 and includes fixes for Go 1.22,
Expand Down Expand Up @@ -277,6 +282,8 @@ Known bugs:
* obfuscating the standard library with `GOPRIVATE=*` is not well supported yet
* `garble test` is temporarily disabled, as it is currently broken

[v0.12.1]: https://github.com/burrowers/garble/releases/tag/v0.12.1

[v0.12.0]: https://github.com/burrowers/garble/releases/tag/v0.12.0
[#690]: https://github.com/burrowers/garble/issues/690
[#812]: https://github.com/burrowers/garble/issues/812
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ to document the current shortcomings of this tool.
var _ = reflect.TypeOf(Message{})
```

* Go programs [are initialized](https://go.dev/ref/spec#Program_initialization) one package at a time,
where imported packages are always initialized before their importers,
and otherwise they are initialized in the lexical order of their import paths.
Since garble obfuscates import paths, this lexical order may change arbitrarily.

* Go plugins are not currently supported; see [#87](https://github.com/burrowers/garble/issues/87).
* Garble requires `git` to patch the linker. That can be avoided once go-gitdiff supports [non-strict patches](https://github.com/bluekeyes/go-gitdiff/issues/30).

Expand Down
2 changes: 1 addition & 1 deletion internal/linker/linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func PatchLinker(goRoot, goVersion, cacheDir, tempDir string) (string, func(), e

patchesVer, modFiles, patches, err := loadLinkerPatches(majorGoVersion)
if err != nil {
panic(fmt.Errorf("cannot retrieve linker patches: %v", err))
return "", nil, fmt.Errorf("cannot retrieve linker patches: %v", err)
}

outputLinkPath, err := cachePath(cacheDir)
Expand Down
28 changes: 15 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ func (w *uniqueLineWriter) Write(p []byte) (n int, err error) {
panic("unexpected use of uniqueLineWriter with -debug unset")
}
if bytes.Count(p, []byte("\n")) != 1 {
panic(fmt.Sprintf("log write wasn't just one line: %q", p))
return 0, fmt.Errorf("log write wasn't just one line: %q", p)
}
if w.seen[string(p)] {
return len(p), nil
Expand Down Expand Up @@ -268,7 +268,10 @@ type errJustExit int
func (e errJustExit) Error() string { return fmt.Sprintf("exit: %d", e) }

func goVersionOK() bool {
const minGoVersion = "go1.22"
const (
minGoVersion = "go1.22" // the first major version we support
maxGoVersion = "go1.23" // the first major version we don't support
)

// rxVersion looks for a version like "go1.2" or "go1.2.3" in `go env GOVERSION`.
rxVersion := regexp.MustCompile(`go\d+\.\d+(?:\.\d+)?`)
Expand All @@ -285,6 +288,10 @@ func goVersionOK() bool {
fmt.Fprintf(os.Stderr, "Go version %q is too old; please upgrade to %s or newer\n", toolchainVersionFull, minGoVersion)
return false
}
if version.Compare(sharedCache.GoVersion, maxGoVersion) >= 0 {
fmt.Fprintf(os.Stderr, "Go version %q is too new; Go linker patches aren't available for %s or later yet\n", toolchainVersionFull, maxGoVersion)
return false
}

// Ensure that the version of Go that built the garble binary is equal or
// newer than cache.GoVersionSemver.
Expand Down Expand Up @@ -1262,7 +1269,7 @@ func (tf *transformer) processImportCfg(flags []string, requiredPkgs []string) (
beforePath, afterPath := pair[0], pair[1]
lpkg, err := listPackage(tf.curPkg, beforePath)
if err != nil {
panic(err) // shouldn't happen
return "", err
}
if lpkg.ToObfuscate {
// Note that beforePath is not the canonical path.
Expand Down Expand Up @@ -1327,7 +1334,7 @@ func (tf *transformer) processImportCfg(flags []string, requiredPkgs []string) (
if strings.HasSuffix(tf.curPkg.ImportPath, ".test]") && strings.HasPrefix(tf.curPkg.ImportPath, impPath) {
continue
}
panic(err) // shouldn't happen
return "", err
}
if lpkg.Name != "main" {
impPath = lpkg.obfuscatedImportPath()
Expand Down Expand Up @@ -1470,7 +1477,7 @@ func computePkgCache(fsCache *cache.Cache, lpkg *listedPackage, pkg *types.Packa
// Shadowing lpkg ensures we don't use the wrong listedPackage below.
lpkg, err := listPackage(lpkg, imp)
if err != nil {
panic(err) // shouldn't happen
return computed, err
}
if lpkg.BuildID == "" {
continue // nothing to load
Expand Down Expand Up @@ -1766,13 +1773,8 @@ func (tf *transformer) useAllImports(file *ast.File) {
continue
}

// Simple import has no ast.Ident and is stored in Implicits separately.
pkgObj := tf.info.Implicits[imp]
if pkgObj == nil {
pkgObj = tf.info.Defs[imp.Name] // renamed or dot import
}

pkgScope := pkgObj.(*types.PkgName).Imported().Scope()
pkgName := tf.info.PkgNameOf(imp)
pkgScope := pkgName.Imported().Scope()
var nameObj types.Object
for _, name := range pkgScope.Names() {
if obj := pkgScope.Lookup(name); obj.Exported() && isSafeForInstanceType(obj.Type()) {
Expand All @@ -1793,7 +1795,7 @@ func (tf *transformer) useAllImports(file *ast.File) {
switch {
case imp.Name == nil: // import "pkg/path"
nameExpr = &ast.SelectorExpr{
X: ast.NewIdent(pkgObj.Name()),
X: ast.NewIdent(pkgName.Name()),
Sel: nameIdent,
}
case imp.Name.Name != ".": // import path2 "pkg/path"
Expand Down
6 changes: 3 additions & 3 deletions shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ func listPackage(from *listedPackage, path string) (*listedPackage, error) {
return pkg, nil
}
if listedRuntimeLinknamed {
panic(fmt.Sprintf("package %q still missing after go list call", path))
return nil, fmt.Errorf("package %q still missing after go list call", path)
}
startTime := time.Now()
missing := make([]string, 0, len(runtimeLinknamed))
Expand All @@ -397,11 +397,11 @@ func listPackage(from *listedPackage, path string) (*listedPackage, error) {
}
// We don't need any information about their dependencies, in this case.
if err := appendListedPackages(missing, false); err != nil {
panic(err) // should never happen
return nil, fmt.Errorf("failed to load missing runtime-linknamed packages: %v", err)
}
pkg, ok := sharedCache.ListedPackages[path]
if !ok {
panic(fmt.Sprintf("std listed another std package that we can't find: %s", path))
return nil, fmt.Errorf("std listed another std package that we can't find: %s", path)
}
listedRuntimeLinknamed = true
log.Printf("listed %d missing runtime-linknamed packages in %s", len(missing), debugSince(startTime))
Expand Down
6 changes: 3 additions & 3 deletions testdata/script/goversion.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ env TOOLCHAIN_GOVERSION='go1.14'
! exec garble build
stderr 'Go version "go1\.14" is too old; please upgrade to go1\.22 or newer'

# We should accept a future stable version.
# We should reject a future stable version, as we don't have linker patches yet.
# Note that we need to bump the version of Go that supposedly built it, too.
env GARBLE_TEST_GOVERSION='go1.28.2'
env TOOLCHAIN_GOVERSION='go1.28.2'
! exec garble build
stderr 'mocking the real build'
stderr 'Go version "go1\.28\.2" is too new; Go linker patches aren''t available for go1\.23 or later yet'

# We should accept custom devel strings.
env TOOLCHAIN_GOVERSION='devel go1.23-somecustomversion'
env TOOLCHAIN_GOVERSION='devel go1.22-somecustomversion'
! exec garble build
stderr 'mocking the real build'

Expand Down
Loading