Skip to content

Commit

Permalink
clarify and test that runtime.GOROOT is not available
Browse files Browse the repository at this point in the history
Closes #878.
  • Loading branch information
mvdan authored and lu4p committed Nov 24, 2024
1 parent b0d3563 commit acec595
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 17 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ to document the current shortcomings of this tool.
* 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).

* APIs like [`runtime.GOROOT`](https://pkg.go.dev/runtime#GOROOT)
and [`runtime/debug.ReadBuildInfo`](https://pkg.go.dev/runtime/debug#ReadBuildInfo)
will not work in obfuscated binaries. This [can affect loading timezones](https://github.com/golang/go/issues/51473#issuecomment-2490564684), for example.

### Contributing

We welcome new contributors. If you would like to contribute, see
Expand Down
53 changes: 36 additions & 17 deletions testdata/script/gogarble.txtar
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Ensure that "does not match any packages" works.
env GOGARBLE=match-absolutely/nothing
! exec garble build -o=out ./standalone
! exec garble build -o=main$exe ./standalone
stderr '^GOGARBLE="match-absolutely/nothing" does not match any packages to be built$'

# A build where just some packages are obfuscated.
env GOGARBLE=test/main/imported
exec garble -literals build -o=out ./importer
exec garble -literals build -o=main$exe ./importer

! binsubstr out 'some long string to obfuscate'
binsubstr out 'some long string to not obfuscate'
! binsubstr main$exe 'some long string to obfuscate'
binsubstr main$exe 'some long string to not obfuscate'

# Obfuscated packages which import non-obfuscated std packages.
# Some of the imported std packages use "import maps" due to vendoring,
# and a past bug made this case fail for "garble build".
env GOGARBLE=test/main
exec garble build -o=out ./stdimporter
exec garble build -o=main$exe ./stdimporter

[short] stop # rebuilding std is slow

Expand All @@ -34,13 +34,19 @@ exec garble build std
# Link a binary importing net/http, which will catch whether or not we
# support ImportMap when linking.
# Also ensure we are obfuscating low-level std packages.
exec garble build -o=out ./stdimporter
exec garble build -o=main$exe ./stdimporter
! stderr . # no warnings
! binsubstr out 'http.ListenAndServe' 'debug.WriteHeapDump' 'time.Now' 'syscall.Listen'
! binsubstr main$exe 'http.ListenAndServe' 'debug.WriteHeapDump' 'time.Now' 'syscall.Listen'

# Ensure that the embedded runtime.GOROOT and runtime.Version are unset.
# Note that testscript sets GOROOT explicitly, which we don't want to use.
env GOROOT=
exec ./main$exe
cmp stdout stdimporter.stdout

# The same low-level std packages appear in plain sight in regular builds.
go build -o=out_regular ./stdimporter
binsubstr out_regular 'http.ListenAndServe' 'debug.WriteHeapDump' 'time.Now' 'syscall.Listen'
go build -o=main_regular$exe ./stdimporter
binsubstr main_regular$exe 'http.ListenAndServe' 'debug.WriteHeapDump' 'time.Now' 'syscall.Listen'

# Also check that a full rebuild is reproducible, via a new GOCACHE.
# This is slow, but necessary to uncover bugs hidden by the build cache.
Expand All @@ -49,8 +55,8 @@ binsubstr out_regular 'http.ListenAndServe' 'debug.WriteHeapDump' 'time.Now' 'sy
[darwin] skip 'see https://github.com/burrowers/garble/issues/609'
env GOCACHE=${WORK}/gocache-empty
exec garble build -a runtime
exec garble build -o=out_rebuild ./stdimporter
bincmp out_rebuild out
exec garble build -o=main_rebuild$exe ./stdimporter
bincmp main_rebuild$exe main$exe
-- go.mod --
module test/main

Expand All @@ -76,17 +82,30 @@ var LongString = "some long string to obfuscate"
package main

import (
"fmt"
"net/http"
"os"
"runtime"
"runtime/debug"
"time"
"syscall"
)

func main() {
http.ListenAndServe("", nil)
// debug.WriteHeapDump is particularly interesting,
// as it is implemented by runtime via a linkname.
debug.WriteHeapDump(1)
time.Now()
syscall.Listen(0, 1)
// Ensure that embedded information in the runtime is missing.
fmt.Printf("runtime.GOROOT: %q\n", runtime.GOROOT())
fmt.Printf("runtime.Version: %q\n", runtime.Version())

// We just want to ensure these build and link OK, but we don't need to run them.
if len(os.Args) > 5 {
http.ListenAndServe("", nil)
// debug.WriteHeapDump is particularly interesting,
// as it is implemented by runtime via a linkname.
debug.WriteHeapDump(1)
time.Now()
syscall.Listen(0, 1)
}
}
-- stdimporter.stdout --
runtime.GOROOT: ""
runtime.Version: "unknown"

0 comments on commit acec595

Please sign in to comment.