Segfault in FetchIPFromSTUNCall
To reproduce:
pea@peabox:bootstrap go test -count=1 -v ./... -run TestGeolocatation
=== RUN TestGeolocatation
9:31AM DBG Disabling DNS over HTTP (not using SSL)
9:31AM DBG Getting ip address
9:31AM WRN Could not get ip address with WebAPIs. Now trying STUN servers.
9:31AM TRC Trying STUN server server=stun.syncthing.net:3478
WE HAVE AN ERROR
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x83139a]
goroutine 9 [running]:
github.com/pion/stun.(*Message).Get(...)
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/attributes.go:223
github.com/pion/stun.(*XORMappedAddress).GetFromAs(0xcc5760?, 0xc000134090?, 0x76d0?)
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/xoraddr.go:88 +0x1a
github.com/pion/stun.(*XORMappedAddress).GetFrom(...)
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/xoraddr.go:149
0xacab.org/leap/tunnel-telemetry/pkg/geolocate.FetchIPFromSTUNCall.func1({{0x73, 0xe4, 0x18, 0xab, 0xa9, 0xaf, 0x60, 0xc8, 0x16, 0x14, ...}, ...})
/home/pea/projects/leap/tunnel-telemetry/pkg/geolocate/stun.go:63 +0xb7
github.com/pion/stun.(*callbackWaitHandler).HandleEvent(0xc0003786c0, {{0x73, 0xe4, 0x18, 0xab, 0xa9, 0xaf, 0x60, 0xc8, 0x16, ...}, ...})
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/client.go:521 +0x5b
github.com/pion/stun.(*clientTransaction).handle(...)
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/client.go:309
github.com/pion/stun.(*Client).handleAgentCallback(0xc0003cfb80, {{0x73, 0xe4, 0x18, 0xab, 0xa9, 0xaf, 0x60, 0xc8, 0x16, ...}, ...})
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/client.go:629 +0x16e
github.com/pion/stun.(*Agent).Collect(0xc000378660, {0x0?, 0xc000077f20?, 0x1170580?})
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/agent.go:176 +0x3e6
github.com/pion/stun.NewClient.func1({0xc000077f98?, 0xc000077f78?, 0x1170580?})
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/client.go:230 +0x31
github.com/pion/stun.(*tickerCollector).Start.func1()
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/client.go:455 +0x90
created by github.com/pion/stun.(*tickerCollector).Start in goroutine 6
/home/pea/go/pkg/mod/github.com/pion/stun@v0.6.1/client.go:447 +0xa5
FAIL 0xacab.org/leap/bitmask-core/pkg/bootstrap 10.853s
FAIL
TestGeolocatation is defined in bitmask-core:pkg/bootstrap/geolocate_test.go.
// FetchIPFromSTUNCall tries to get our public IP using the passed
// stun uri. It returns an error of the operation does not succeed.
func FetchIPFromSTUNCall(uri string) (string, error) {
u, err := stun.ParseURI("stun:" + uri)
if err != nil {
return "", err
}
// Create a "connection" to STUN server.
c, err := stun.DialURI(u, &stun.DialConfig{})
if err != nil {
return "", err
}
// Build binding request with random transaction id.
message := stun.MustBuild(stun.TransactionID, stun.BindingRequest)
errch, ipch := make(chan error, 1), make(chan string, 1)
// Send request to STUN server, waiting for response message.
if err := c.Do(message, func(res stun.Event) {
if res.Error != nil {
errch <- res.Error
}
// Decode XOR-MAPPED-ADDRESS attribute from message.
var xorAddr stun.XORMappedAddress
if err := xorAddr.GetFrom(res.Message); err != nil {
errch <- err
}
ipch <- xorAddr.IP.String()
}); err != nil {
return "", err
}
// TODO(ain): add timeout/ctx
select {
case err := <-errch:
return "127.0.0.1", err
case ip := <-ipch:
return ip, nil
}
}
The problem: Sometimes we are in this code path:
if res.Error != nil {
errch <- res.Error
}
But at this point we don't return. We need a break or an else at this point to not continue at this point.
I don't know why there are channels. We could just return an error and return from the function if an error happens. Don't know why it is that complicated.