The Go programming language has the concept of a panic
.
Panic is a built-in function that stops the ordinary flow of control and begins panicking. When the function F calls panic, execution of F stops, any deferred functions in F are executed normally, and then F returns to its caller. To the caller, F then behaves like a call to panic. The process continues up the stack until all functions in the current goroutine have returned, at which point the program crashes. Panics can be initiated by invoking panic directly. They can also be caused by runtime errors, such as out-of-bounds array accesses. - Andrew Gerrand. August 2010
Let’s see this in action with some code I’m building and running on my MacBook. Save this file as main.go
package main
// Adapted from https://gobyexample.com/regular-expressions
import (
"fmt"
"regexp"
)
func main() {
r, _ := regexp.Compile("p([a-z]+)ch")
fmt.Println(r.MatchString("peach"))
// Too many ')' in the regex
r, _ = regexp.Compile("p([a-z]+))ch")
fmt.Println(r.MatchString("peach"))
}
We can build and test this from the command line (assuming you have Go installed).
go build main.go && ./main
On my machine I get the following output (I’ve deleted content not relevant to the discussion)
...
regexp.(*Regexp).doExecute(0x10462923b?, ...
/opt/homebrew/Cellar/go/1.19.1/libexec/src/regexp/exec.go:527 +0x50
regexp.(*Regexp).doMatch(...)
/opt/homebrew/Cellar/go/1.19.1/libexec/src/regexp/exec.go:514
regexp.(*Regexp).MatchString(...)
/opt/homebrew/Cellar/go/1.19.1/libexec/src/regexp/regexp.go:533
main.main()
/Users/alec/projects/NiceGoPanics/main.go:18 +0x114
You can see which version of Go I am using (1.19.1), that I’m building on macOS, and the project directory were my source code is located.
This will probably be confusing to any user reporting the problem, and could give a cracker information about potential attack vectors.
In Go 1.13 (September 2019) the -trimpath
build flag was introduced.
This strips out a lot of extraneous information.
The new go build flag -trimpath removes all file system paths from the compiled executable, to improve build reproducibility. - Go 1.13 release notes
Let’s see it in action
go build -trimpath main.go && ./main
...
regexp.(*Regexp).doExecute(0x100fd923b?, ...
regexp/exec.go:527 +0x50
regexp.(*Regexp).doMatch(...)
regexp/exec.go:514
regexp.(*Regexp).MatchString(...)
regexp/regexp.go:533
main.main()
./main.go:18 +0x114
Much better. So make sure you add -trimpath
to all your production builds.
Big thanks to my colleague, Tom Clift, who pointed out -trimpath
to me.
However, this does not remove all the information. For example:
$ go version -m main
main: go1.19.1
path command-line-arguments
build -compiler=gc
build -trimpath=true
build CGO_ENABLED=1
build GOARCH=arm64
build GOOS=darwin