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

regexp: unexpected return pc for regexp.(*Regexp).tryBacktrack called #53989

Closed
liggitt opened this issue Jul 21, 2022 · 18 comments
Closed

regexp: unexpected return pc for regexp.(*Regexp).tryBacktrack called #53989

liggitt opened this issue Jul 21, 2022 · 18 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@liggitt
Copy link
Contributor

liggitt commented Jul 21, 2022

What version of Go are you using (go version)?

$ go version

go version go1.19rc2 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env

GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOVCS=""
GOVERSION="go1.19rc2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1385535929=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Encountered a runtime crash on 1.19rc2 in the regexp package when running a configuration that uses plugins. The specific configuration was https://github.com/golangci/golangci-lint combined with a custom linter plugin which happened to use a regexp internally. The original issue was kubernetes/kubernetes#111297

The following is a minimal reproducer which is compiled as a plugin and then run:

plugin.go:

// To reproduce, run:
// 
// go build -buildmode=plugin ./plugin.go
// go run ./plugin.go

package main

import (
	"context"
	"fmt"
	"plugin"
	"regexp"
	"time"
)

type EvaluatorInterface interface {
	Evaluate()
	EvaluateLoop(context.Context)
}

type EvaluatorImpl struct{}

func (EvaluatorImpl) Evaluate() {
	R.MatchString("123")
}
func (EvaluatorImpl) EvaluateLoop(ctx context.Context) {
	for ctx.Err() == nil {
		R.MatchString("123")
	}
}

var Evaluator EvaluatorImpl

var R = regexp.MustCompile(".*")

func main() {
	ctx, cancel := context.WithCancel(context.Background())

	// works
	go mainLoop(ctx)
	time.Sleep(time.Second)

	// breaks
	go pluginLoop(ctx)
	time.Sleep(time.Second)

	// breaks
	go mainLoopPluginEval(ctx)
	time.Sleep(time.Second)

	cancel()
}

func getEvaluator() EvaluatorInterface {
	p, err := plugin.Open("plugin.so")
	if err != nil {
		panic(err)
	}
	evaluatorInterface, err := p.Lookup("Evaluator")
	if err != nil {
		panic(err)
	}
	evaluator, ok := evaluatorInterface.(EvaluatorInterface)
	if !ok {
		panic("doesn't implement EvaluatorInterface")
	}
	return evaluator
}

// loops and evaluates inside the main binary
func mainLoop(ctx context.Context) {
	fmt.Println("mainLoop")
	for ctx.Err() == nil {
		R.MatchString("123")
	}
}

// loops and evaluates inside the plugin
func pluginLoop(ctx context.Context) {
	fmt.Println("pluginLoop")
	getEvaluator().EvaluateLoop(ctx)
}

// loops inside the main binary, evaluates inside the plugin
func mainLoopPluginEval(ctx context.Context) {
	fmt.Println("mainLoopPluginEval")
	evaluator := getEvaluator()
	for ctx.Err() == nil {
		evaluator.Evaluate()
	}
}

Running that on 1.19rc2 produces:

$ go version
go version go1.19rc2 linux/amd64

$ go build -buildmode=plugin ./plugin.go

$ go run ./plugin.go
mainLoop
pluginLoop
mainLoop
pluginLoop
runtime: g 3: unexpected return pc for regexp.(*Regexp).tryBacktrack called from 0xc00012e000
stack: frame={sp:0xc000129d08, fp:0xc000129dc0} stack=[0xc000128000,0xc00012a000)
0x000000c000129c08:  0x000000c000129c10  0x00000000004aabe0 <runtime.addOneOpenDeferFrame.func1+0x0000000000000000> 
0x000000c000129c18:  0x0000000000560005 <regexp.(*Regexp).tryBacktrack+0x0000000000000cc5>  0x000000c000129d08 
0x000000c000129c28:  0x000000c000007380  0x0000000000000000 
0x000000c000129c38:  0x000000c000129cf8  0x00000000004ab3d2 <runtime.gopanic+0x0000000000000112> 
0x000000c000129c48:  0x000000c000129c88  0x00007f9c5d8cf2e5 <runtime.(*mcache).refill+0x00000000000001e5> 
0x000000c000129c58:  0x00000000006cc9e0  0x00007f9c5d8daaa7 <runtime.(*gcControllerState).heapGoalInternal+0x0000000000000027> 
0x000000c000129c68:  0x00007f9c877e2290  0x0000000000400000 
0x000000c000129c78:  0x000000c000129cb8  0x00007f9c5d8dabe5 <runtime.(*gcControllerState).trigger+0x0000000000000025> 
0x000000c000129c88:  0x00000000006cd820  0x00007f9c5d8c51be <runtime.(*mcache).nextFree+0x000000000000009e> 
0x000000c000129c98:  0x00007f9c877e2180  0x0000000000400000 
0x000000c000129ca8:  0x000000c000129ce8  0x000000c0000073a0 
0x000000c000129cb8:  0x000000c000007380  0x0000000000000000 
0x000000c000129cc8:  0x000000000057d2a0  0x00000000005ce300 
0x000000c000129cd8:  0x0000000000000000  0x0000000000000000 
0x000000c000129ce8:  0x0000000000000000  0x0000000000000000 
0x000000c000129cf8:  0x000000c000129da0  0x0000000000560005 <regexp.(*Regexp).tryBacktrack+0x0000000000000cc5> 
0x000000c000129d08: <0x000000000057d2a0  0x00000000005ce300 
0x000000c000129d18:  0x00007f9c877d7108  0x0000000000008000 
0x000000c000129d28:  0x000000c000058c00  0x000000c000132000 
0x000000c000129d38:  0x0000000000000000  0x00000000000000a0 
0x000000c000129d48:  0x000000c000009d70  0x00007f9c00000000 
0x000000c000129d58:  0x0000000000008000  0x000000000057d3a0 
0x000000c000129d68:  0x0000000000000001  0x0000000000000000 
0x000000c000129d78:  0x00007f9c5d9a14d3 <regexp.(*bitState).reset+0x0000000000000113>  0x000000000000000a 
0x000000c000129d88:  0x0000000000000000  0x000000c0000000a0 
0x000000c000129d98:  0x000000c0000000a0  0x000000c0000000a0 
0x000000c000129da8:  0x00007f9c5d9a290d <regexp.(*Regexp).backtrack+0x000000000000032d>  0x000000c000000140 
0x000000c000129db8: !0x000000c00012e000 >0x00000000005ceb88 
0x000000c000129dc8:  0x000000c00012e080  0x000000c000129e80 
0x000000c000129dd8:  0x000000000047fd9d <runtime.(*itab).init+0x000000000000019d>  0x000000c00007e090 
0x000000c000129de8:  0x0000000000000003  0x00000000005ceb88 
0x000000c000129df8:  0x0000000000000002  0x0000000000000000 
0x000000c000129e08:  0x000000c00012e080  0x000000c00012e000 
0x000000c000129e18:  0x000000000000000c  0x000000c000129ed0 
0x000000c000129e28:  0x00007f9c5d9a5470 <regexp.(*Regexp).doExecute+0x0000000000000290>  0x00000000006ccd00 
0x000000c000129e38:  0x0000000000000000  0x0000000000000000 
0x000000c000129e48:  0x000000c000000140  0x0000000000000000 
0x000000c000129e58:  0x0000000000000000  0x0000000000000000 
0x000000c000129e68:  0x00007f9c5d9b10d4  0x0000000000000003 
0x000000c000129e78:  0x0000000000000000  0x000000c000129ec8 
0x000000c000129e88:  0x000000000047f853 <runtime.getitab+0x0000000000000153>  0x00007f9c5fb5b7d0 
0x000000c000129e98:  0x0000000000000000  0x0000000000000000 
0x000000c000129ea8:  0x0000000000000000  0x000000c00007e060 
0x000000c000129eb8:  0x000000c00011e000 
fatal error: unknown caller pc

runtime stack:
runtime.throw({0x5a1909?, 0x6911a0?})
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/panic.go:1047 +0x5d fp=0x7f9c5f3529e8 sp=0x7f9c5f3529b8 pc=0x4ababd
runtime.gentraceback(0x7f9c877e21e3?, 0x8?, 0xc000034000?, 0x7f9c5f352dc0?, 0x0, 0x0, 0x7fffffff, 0x7f9c5f352da8, 0x28?, 0x0)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/traceback.go:258 +0x1cf7 fp=0x7f9c5f352d58 sp=0x7f9c5f3529e8 pc=0x4d0197
runtime.addOneOpenDeferFrame.func1()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/panic.go:645 +0x6b fp=0x7f9c5f352dd0 sp=0x7f9c5f352d58 pc=0x4aac4b
runtime.systemstack()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:492 +0x49 fp=0x7f9c5f352dd8 sp=0x7f9c5f352dd0 pc=0x4d9de9

goroutine 3 [running]:
runtime.systemstack_switch()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:459 fp=0xc000129c08 sp=0xc000129c00 pc=0x4d9d80
runtime.addOneOpenDeferFrame(0xc000129c88?, 0x7f9c5d8cf2e5?, 0x6cc9e0?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/panic.go:644 +0x69 fp=0xc000129c48 sp=0xc000129c08 pc=0x4aab89
panic({0x57d2a0, 0x5ce300})
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/panic.go:844 +0x112 fp=0xc000129d08 sp=0xc000129c48 pc=0x4ab3d2
runtime: g 3: unexpected return pc for regexp.(*Regexp).tryBacktrack called from 0xc00012e000
stack: frame={sp:0xc000129d08, fp:0xc000129dc0} stack=[0xc000128000,0xc00012a000)
0x000000c000129c08:  0x000000c000129c10  0x00000000004aabe0 <runtime.addOneOpenDeferFrame.func1+0x0000000000000000> 
0x000000c000129c18:  0x0000000000560005 <regexp.(*Regexp).tryBacktrack+0x0000000000000cc5>  0x000000c000129d08 
0x000000c000129c28:  0x000000c000007380  0x0000000000000000 
0x000000c000129c38:  0x000000c000129cf8  0x00000000004ab3d2 <runtime.gopanic+0x0000000000000112> 
0x000000c000129c48:  0x000000c000129c88  0x00007f9c5d8cf2e5 <runtime.(*mcache).refill+0x00000000000001e5> 
0x000000c000129c58:  0x00000000006cc9e0  0x00007f9c5d8daaa7 <runtime.(*gcControllerState).heapGoalInternal+0x0000000000000027> 
0x000000c000129c68:  0x00007f9c877e2290  0x0000000000400000 
0x000000c000129c78:  0x000000c000129cb8  0x00007f9c5d8dabe5 <runtime.(*gcControllerState).trigger+0x0000000000000025> 
0x000000c000129c88:  0x00000000006cd820  0x00007f9c5d8c51be <runtime.(*mcache).nextFree+0x000000000000009e> 
0x000000c000129c98:  0x00007f9c877e2180  0x0000000000400000 
0x000000c000129ca8:  0x000000c000129ce8  0x000000c0000073a0 
0x000000c000129cb8:  0x000000c000007380  0x0000000000000000 
0x000000c000129cc8:  0x000000000057d2a0  0x00000000005ce300 
0x000000c000129cd8:  0x0000000000000000  0x0000000000000000 
0x000000c000129ce8:  0x0000000000000000  0x0000000000000000 
0x000000c000129cf8:  0x000000c000129da0  0x0000000000560005 <regexp.(*Regexp).tryBacktrack+0x0000000000000cc5> 
0x000000c000129d08: <0x000000000057d2a0  0x00000000005ce300 
0x000000c000129d18:  0x00007f9c877d7108  0x0000000000008000 
0x000000c000129d28:  0x000000c000058c00  0x000000c000132000 
0x000000c000129d38:  0x0000000000000000  0x00000000000000a0 
0x000000c000129d48:  0x000000c000009d70  0x00007f9c00000000 
0x000000c000129d58:  0x0000000000008000  0x000000000057d3a0 
0x000000c000129d68:  0x0000000000000001  0x0000000000000000 
0x000000c000129d78:  0x00007f9c5d9a14d3 <regexp.(*bitState).reset+0x0000000000000113>  0x000000000000000a 
0x000000c000129d88:  0x0000000000000000  0x000000c0000000a0 
0x000000c000129d98:  0x000000c0000000a0  0x000000c0000000a0 
0x000000c000129da8:  0x00007f9c5d9a290d <regexp.(*Regexp).backtrack+0x000000000000032d>  0x000000c000000140 
0x000000c000129db8: !0x000000c00012e000 >0x00000000005ceb88 
0x000000c000129dc8:  0x000000c00012e080  0x000000c000129e80 
0x000000c000129dd8:  0x000000000047fd9d <runtime.(*itab).init+0x000000000000019d>  0x000000c00007e090 
0x000000c000129de8:  0x0000000000000003  0x00000000005ceb88 
0x000000c000129df8:  0x0000000000000002  0x0000000000000000 
0x000000c000129e08:  0x000000c00012e080  0x000000c00012e000 
0x000000c000129e18:  0x000000000000000c  0x000000c000129ed0 
0x000000c000129e28:  0x00007f9c5d9a5470 <regexp.(*Regexp).doExecute+0x0000000000000290>  0x00000000006ccd00 
0x000000c000129e38:  0x0000000000000000  0x0000000000000000 
0x000000c000129e48:  0x000000c000000140  0x0000000000000000 
0x000000c000129e58:  0x0000000000000000  0x0000000000000000 
0x000000c000129e68:  0x00007f9c5d9b10d4  0x0000000000000003 
0x000000c000129e78:  0x0000000000000000  0x000000c000129ec8 
0x000000c000129e88:  0x000000000047f853 <runtime.getitab+0x0000000000000153>  0x00007f9c5fb5b7d0 
0x000000c000129e98:  0x0000000000000000  0x0000000000000000 
0x000000c000129ea8:  0x0000000000000000  0x000000c00007e060 
0x000000c000129eb8:  0x000000c00011e000 
regexp.(*Regexp).tryBacktrack(0x5ceb88, 0xc00012e080, {0xc000129e80?, 0x47fd9d}, 0x7e090?, 0x3?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/regexp/backtrack.go:172 +0xcc5 fp=0xc000129dc0 sp=0xc000129d08 pc=0x560005
created by main.main
	/usr/local/google/home/liggitt/tmp/119regex/plugin.go:42 +0xd5

goroutine 1 [sleep]:
runtime.gopark(0x33d97f6c6b64c?, 0xc000062f18?, 0xc0?, 0x6c?, 0xc000012018?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000062f08 sp=0xc000062ee8 pc=0x4ae9f6
time.Sleep(0x3b9aca00)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/time.go:195 +0x135 fp=0xc000062f48 sp=0xc000062f08 pc=0x4d8e55
main.main()
	/usr/local/google/home/liggitt/tmp/119regex/plugin.go:43 +0xdf fp=0xc000062f80 sp=0xc000062f48 pc=0x56cb9f
runtime.main()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:250 +0x212 fp=0xc000062fe0 sp=0xc000062f80 pc=0x4ae632
runtime.goexit()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000062fe8 sp=0xc000062fe0 pc=0x4dbfa1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000054fb0 sp=0xc000054f90 pc=0x4ae9f6
runtime.goparkunlock(...)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:369
runtime.forcegchelper()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:302 +0xad fp=0xc000054fe0 sp=0xc000054fb0 pc=0x4ae88d
runtime.goexit()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000054fe8 sp=0xc000054fe0 pc=0x4dbfa1
created by runtime.init.6
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:290 +0x25

goroutine 18 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000050790 sp=0xc000050770 pc=0x4ae9f6
runtime.goparkunlock(...)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:369
runtime.bgsweep(0x0?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgcsweep.go:278 +0x8e fp=0xc0000507c8 sp=0xc000050790 pc=0x499cae
runtime.gcenable.func1()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgc.go:178 +0x26 fp=0xc0000507e0 sp=0xc0000507c8 pc=0x48e8a6
runtime.goexit()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc0000507e8 sp=0xc0000507e0 pc=0x4dbfa1
created by runtime.gcenable
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgc.go:178 +0x6b

goroutine 19 [GC scavenge wait]:
runtime.gopark(0xc000096000?, 0x5cd960?, 0x1?, 0x0?, 0x0?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000050f70 sp=0xc000050f50 pc=0x4ae9f6
runtime.goparkunlock(...)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:369
runtime.(*scavengerState).park(0x69e280)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgcscavenge.go:389 +0x53 fp=0xc000050fa0 sp=0xc000050f70 pc=0x497cd3
runtime.bgscavenge(0x0?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgcscavenge.go:617 +0x45 fp=0xc000050fc8 sp=0xc000050fa0 pc=0x4982c5
runtime.gcenable.func2()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgc.go:179 +0x26 fp=0xc000050fe0 sp=0xc000050fc8 pc=0x48e846
runtime.goexit()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000050fe8 sp=0xc000050fe0 pc=0x4dbfa1
created by runtime.gcenable
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mgc.go:179 +0xaa

goroutine 20 [finalizer wait]:
runtime.gopark(0x69e760?, 0xc00008a820?, 0x0?, 0x0?, 0xc000054770?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000054628 sp=0xc000054608 pc=0x4ae9f6
runtime.goparkunlock(...)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/proc.go:369
runtime.runfinq()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mfinal.go:180 +0x10f fp=0xc0000547e0 sp=0xc000054628 pc=0x48d9af
runtime.goexit()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc0000547e8 sp=0xc0000547e0 pc=0x4dbfa1
created by runtime.createfing
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/mfinal.go:157 +0x45

goroutine 21 [runnable]:
context.(*cancelCtx).Err(0xc00009a040?)
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/context/context.go:373 +0x9b fp=0xc000063f38 sp=0xc000063f30 pc=0x50009b
main.mainLoop({0x5ce9b8, 0xc00009a040})
	/usr/local/google/home/liggitt/tmp/119regex/plugin.go:71 +0xb4 fp=0xc000063fc0 sp=0xc000063f38 pc=0x56cf54
main.main.func1()
	/usr/local/google/home/liggitt/tmp/119regex/plugin.go:38 +0x2a fp=0xc000063fe0 sp=0xc000063fc0 pc=0x56cd0a
runtime.goexit()
	/usr/local/google/home/liggitt/.gvm/gos/go1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000063fe8 sp=0xc000063fe0 pc=0x4dbfa1
created by main.main
	/usr/local/google/home/liggitt/tmp/119regex/plugin.go:38 +0x85
exit status 2

Running that on go1.18.4 works fine:

$ go version
go version go1.18.4 linux/amd64

$ go build -buildmode=plugin ./plugin.go

$ go run ./plugin.go
mainLoop
pluginLoop
mainLoopPluginEval

What did you expect to see?

Regexp calls inside a plugin work.

What did you see instead?

Regexp calls inside a plugin trigger runtime errors.

@dims found 0293c51, which looks related. Reverting that fixed the issue in the linter scenario we encountered, but did not resolve the issue with this reproducer edit: reverting 0293c51 did not fix the linter scenario, we were mistaken about that

@cherrymui
Copy link
Member

Could you show the full stack trace of the failure? Thanks.

@dims
Copy link

dims commented Jul 21, 2022

@cherrymui Please see the entire trace below

$ go run ./plugin.go
mainLoop
pluginLoop
runtime: g 18: unexpected return pc for regexp.(*Regexp).tryBacktrack called from 0xc0001c00a0
stack: frame={sp:0xc0001bbcf8, fp:0xc0001bbdb8} stack=[0xc0001ba000,0xc0001bc000)
0x000000c0001bbbf8:  0x000000c0001bbc00  0x00000000004a9de0 <runtime.addOneOpenDeferFrame.func1+0x0000000000000000>
0x000000c0001bbc08:  0x000000000055f1f0 <regexp.(*Regexp).tryBacktrack+0x0000000000000cb0>  0x000000c0001bbcf8
0x000000c0001bbc18:  0x000000c000182000  0x0000000000000000
0x000000c0001bbc28:  0x000000c0001bbce8  0x00000000004aa5d2 <runtime.gopanic+0x0000000000000112>
0x000000c0001bbc38:  0x00007fabe2742648  0x0000000000000000
0x000000c0001bbc48:  0x000000c0001bbc88  0x00007fabe12be745 <runtime.(*mcache).refill+0x00000000000001e5>
0x000000c0001bbc58:  0x00000000008c99e0  0x00007fabe12c9f07 <runtime.(*gcControllerState).heapGoalInternal+0x0000000000000027>
0x000000c0001bbc68:  0x00007fabe2742758  0x0000000000400000
0x000000c0001bbc78:  0x000000c0001bbcb8  0x00007fabe12ca045 <runtime.(*gcControllerState).trigger+0x0000000000000025>
0x000000c0001bbc88:  0x00000000008ca820  0x00007fabe12b461e <runtime.(*mcache).nextFree+0x000000000000009e>
0x000000c0001bbc98:  0x00007fabe2742648  0x000000c000182020
0x000000c0001bbca8:  0x000000c000182000  0x0000000000000000
0x000000c0001bbcb8:  0x000000000057c320  0x00000000005cd3b0
0x000000c0001bbcc8:  0x0000000000000000  0x0000000000000000
0x000000c0001bbcd8:  0x0000000000000000  0x0000000000000000
0x000000c0001bbce8:  0x000000c0001bbda0  0x000000000055f1f0 <regexp.(*Regexp).tryBacktrack+0x0000000000000cb0>
0x000000c0001bbcf8: <0x000000000057c320  0x00000000005cd3b0
0x000000c0001bbd08:  0x00007fabe2742648  0x0000000000000000
0x000000c0001bbd18:  0x00007fac0bdcda68  0x0000000000008000
0x000000c0001bbd28:  0x000000c00006a800  0x000000c0001c8000
0x000000c0001bbd38:  0x0000000000000000  0x0000010000000000
0x000000c0001bbd48:  0x000000c0001bbd70  0x00007fabe12f3f92 <runtime.makeslice+0x0000000000000052>
0x000000c0001bbd58:  0x0000000000008000  0x0000000000000000
0x000000c0001bbd68:  0x0000000000000001  0x000000c0001c4038
0x000000c0001bbd78:  0x0000000100000000  0x0000000000000005
0x000000c0001bbd88:  0x0000000000000000  0x0000000000000000
0x000000c0001bbd98:  0x0000000000000000  0x0000000000000000
0x000000c0001bbda8:  0x00007fabe1391dcd <regexp.(*Regexp).backtrack+0x000000000000032d> !0x000000c0001c00a0
0x000000c0001bbdb8: >0x000000c0001c4000  0x00000000005cdc08
0x000000c0001bbdc8:  0x000000c0001c4080  0x000000c0001bbe80
0x000000c0001bbdd8:  0x000000000047ef9d <runtime.(*itab).init+0x000000000000019d>  0x000000c000192090
0x000000c0001bbde8:  0x0000000000000003  0x00000000005cdc08
0x000000c0001bbdf8:  0x0000000000000002  0x0000000000000000
0x000000c0001bbe08:  0x000000c0001c4080  0x000000c0001c4000
0x000000c0001bbe18:  0x000000000000000c  0x000000c0001bbed0
0x000000c0001bbe28:  0x00007fabe13949f0 <regexp.(*Regexp).doExecute+0x0000000000000290>  0x00000000008c9d00
0x000000c0001bbe38:  0x0000000000000000  0x0000000000000000
0x000000c0001bbe48:  0x000000c0001c00a0  0x0000000000000000
0x000000c0001bbe58:  0x0000000000000000  0x0000000000000000
0x000000c0001bbe68:  0x00007fabe139feb4  0x0000000000000003
0x000000c0001bbe78:  0x0000000000000000  0x000000c0001bbec8
0x000000c0001bbe88:  0x000000000047ea53 <runtime.getitab+0x0000000000000153>  0x00007fabe17006d8
0x000000c0001bbe98:  0x0000000000000000  0x0000000000000000
0x000000c0001bbea8:  0x0000000000000000  0x000000c000192060
fatal error: unknown caller pc

runtime stack:
runtime.throw({0x5a0989?, 0x88e1a0?})
	/usr/lib/go-1.19rc2/src/runtime/panic.go:1047 +0x5d fp=0x7fabe3780a88 sp=0x7fabe3780a58 pc=0x4aacbd
runtime.gentraceback(0x7fabe27426ab?, 0x8?, 0xc00002ea00?, 0x7fabe3780e60?, 0x0, 0x0, 0x7fffffff, 0x7fabe3780e48, 0x28?, 0x0)
	/usr/lib/go-1.19rc2/src/runtime/traceback.go:258 +0x1cf7 fp=0x7fabe3780df8 sp=0x7fabe3780a88 pc=0x4cf397
runtime.addOneOpenDeferFrame.func1()
	/usr/lib/go-1.19rc2/src/runtime/panic.go:645 +0x6b fp=0x7fabe3780e70 sp=0x7fabe3780df8 pc=0x4a9e4b
runtime.systemstack()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:492 +0x49 fp=0x7fabe3780e78 sp=0x7fabe3780e70 pc=0x4d8fe9

goroutine 18 [running]:
runtime.systemstack_switch()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:459 fp=0xc0001bbbf8 sp=0xc0001bbbf0 pc=0x4d8f80
runtime.addOneOpenDeferFrame(0x7fabe2742648?, 0x0?, 0xc0001bbc88?)
	/usr/lib/go-1.19rc2/src/runtime/panic.go:644 +0x69 fp=0xc0001bbc38 sp=0xc0001bbbf8 pc=0x4a9d89
panic({0x57c320, 0x5cd3b0})
	/usr/lib/go-1.19rc2/src/runtime/panic.go:844 +0x112 fp=0xc0001bbcf8 sp=0xc0001bbc38 pc=0x4aa5d2
runtime: g 18: unexpected return pc for regexp.(*Regexp).tryBacktrack called from 0xc0001c00a0
stack: frame={sp:0xc0001bbcf8, fp:0xc0001bbdb8} stack=[0xc0001ba000,0xc0001bc000)
0x000000c0001bbbf8:  0x000000c0001bbc00  0x00000000004a9de0 <runtime.addOneOpenDeferFrame.func1+0x0000000000000000>
0x000000c0001bbc08:  0x000000000055f1f0 <regexp.(*Regexp).tryBacktrack+0x0000000000000cb0>  0x000000c0001bbcf8
0x000000c0001bbc18:  0x000000c000182000  0x0000000000000000
0x000000c0001bbc28:  0x000000c0001bbce8  0x00000000004aa5d2 <runtime.gopanic+0x0000000000000112>
0x000000c0001bbc38:  0x00007fabe2742648  0x0000000000000000
0x000000c0001bbc48:  0x000000c0001bbc88  0x00007fabe12be745 <runtime.(*mcache).refill+0x00000000000001e5>
0x000000c0001bbc58:  0x00000000008c99e0  0x00007fabe12c9f07 <runtime.(*gcControllerState).heapGoalInternal+0x0000000000000027>
0x000000c0001bbc68:  0x00007fabe2742758  0x0000000000400000
0x000000c0001bbc78:  0x000000c0001bbcb8  0x00007fabe12ca045 <runtime.(*gcControllerState).trigger+0x0000000000000025>
0x000000c0001bbc88:  0x00000000008ca820  0x00007fabe12b461e <runtime.(*mcache).nextFree+0x000000000000009e>
0x000000c0001bbc98:  0x00007fabe2742648  0x000000c000182020
0x000000c0001bbca8:  0x000000c000182000  0x0000000000000000
0x000000c0001bbcb8:  0x000000000057c320  0x00000000005cd3b0
0x000000c0001bbcc8:  0x0000000000000000  0x0000000000000000
0x000000c0001bbcd8:  0x0000000000000000  0x0000000000000000
0x000000c0001bbce8:  0x000000c0001bbda0  0x000000000055f1f0 <regexp.(*Regexp).tryBacktrack+0x0000000000000cb0>
0x000000c0001bbcf8: <0x000000000057c320  0x00000000005cd3b0
0x000000c0001bbd08:  0x00007fabe2742648  0x0000000000000000
0x000000c0001bbd18:  0x00007fac0bdcda68  0x0000000000008000
0x000000c0001bbd28:  0x000000c00006a800  0x000000c0001c8000
0x000000c0001bbd38:  0x0000000000000000  0x0000010000000000
0x000000c0001bbd48:  0x000000c0001bbd70  0x00007fabe12f3f92 <runtime.makeslice+0x0000000000000052>
0x000000c0001bbd58:  0x0000000000008000  0x0000000000000000
0x000000c0001bbd68:  0x0000000000000001  0x000000c0001c4038
0x000000c0001bbd78:  0x0000000100000000  0x0000000000000005
0x000000c0001bbd88:  0x0000000000000000  0x0000000000000000
0x000000c0001bbd98:  0x0000000000000000  0x0000000000000000
0x000000c0001bbda8:  0x00007fabe1391dcd <regexp.(*Regexp).backtrack+0x000000000000032d> !0x000000c0001c00a0
0x000000c0001bbdb8: >0x000000c0001c4000  0x00000000005cdc08
0x000000c0001bbdc8:  0x000000c0001c4080  0x000000c0001bbe80
0x000000c0001bbdd8:  0x000000000047ef9d <runtime.(*itab).init+0x000000000000019d>  0x000000c000192090
0x000000c0001bbde8:  0x0000000000000003  0x00000000005cdc08
0x000000c0001bbdf8:  0x0000000000000002  0x0000000000000000
0x000000c0001bbe08:  0x000000c0001c4080  0x000000c0001c4000
0x000000c0001bbe18:  0x000000000000000c  0x000000c0001bbed0
0x000000c0001bbe28:  0x00007fabe13949f0 <regexp.(*Regexp).doExecute+0x0000000000000290>  0x00000000008c9d00
0x000000c0001bbe38:  0x0000000000000000  0x0000000000000000
0x000000c0001bbe48:  0x000000c0001c00a0  0x0000000000000000
0x000000c0001bbe58:  0x0000000000000000  0x0000000000000000
0x000000c0001bbe68:  0x00007fabe139feb4  0x0000000000000003
0x000000c0001bbe78:  0x0000000000000000  0x000000c0001bbec8
0x000000c0001bbe88:  0x000000000047ea53 <runtime.getitab+0x0000000000000153>  0x00007fabe17006d8
0x000000c0001bbe98:  0x0000000000000000  0x0000000000000000
0x000000c0001bbea8:  0x0000000000000000  0x000000c000192060
regexp.(*Regexp).tryBacktrack(0xc0001c4000, 0x5cdc08, {0xc0001c4080?, 0xc0001bbe80}, 0x47ef9d?, 0xc000192090?)
	/usr/lib/go-1.19rc2/src/regexp/backtrack.go:172 +0xcb0 fp=0xc0001bbdb8 sp=0xc0001bbcf8 pc=0x55f1f0
created by main.main
	/home/dims/junk/plugin.go:44 +0xd5

goroutine 1 [sleep]:
runtime.gopark(0x9ffb5649e60e?, 0xc000079f18?, 0xc0?, 0x5e?, 0xc000180000?)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000079f08 sp=0xc000079ee8 pc=0x4adbf6
time.Sleep(0x3b9aca00)
	/usr/lib/go-1.19rc2/src/runtime/time.go:195 +0x135 fp=0xc000079f48 sp=0xc000079f08 pc=0x4d8055
main.main()
	/home/dims/junk/plugin.go:45 +0xdf fp=0xc000079f80 sp=0xc000079f48 pc=0x56be7f
runtime.main()
	/usr/lib/go-1.19rc2/src/runtime/proc.go:250 +0x212 fp=0xc000079fe0 sp=0xc000079f80 pc=0x4ad832
runtime.goexit()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000079fe8 sp=0xc000079fe0 pc=0x4db1a1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000066fb0 sp=0xc000066f90 pc=0x4adbf6
runtime.goparkunlock(...)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:369
runtime.forcegchelper()
	/usr/lib/go-1.19rc2/src/runtime/proc.go:302 +0xad fp=0xc000066fe0 sp=0xc000066fb0 pc=0x4ada8d
runtime.goexit()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000066fe8 sp=0xc000066fe0 pc=0x4db1a1
created by runtime.init.6
	/usr/lib/go-1.19rc2/src/runtime/proc.go:290 +0x25

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000067790 sp=0xc000067770 pc=0x4adbf6
runtime.goparkunlock(...)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:369
runtime.bgsweep(0x0?)
	/usr/lib/go-1.19rc2/src/runtime/mgcsweep.go:278 +0x8e fp=0xc0000677c8 sp=0xc000067790 pc=0x498eae
runtime.gcenable.func1()
	/usr/lib/go-1.19rc2/src/runtime/mgc.go:178 +0x26 fp=0xc0000677e0 sp=0xc0000677c8 pc=0x48daa6
runtime.goexit()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc0000677e8 sp=0xc0000677e0 pc=0x4db1a1
created by runtime.gcenable
	/usr/lib/go-1.19rc2/src/runtime/mgc.go:178 +0x6b

goroutine 4 [GC scavenge wait]:
runtime.gopark(0xc00007e000?, 0x5cca08?, 0x1?, 0x0?, 0x0?)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000067f70 sp=0xc000067f50 pc=0x4adbf6
runtime.goparkunlock(...)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:369
runtime.(*scavengerState).park(0x89b280)
	/usr/lib/go-1.19rc2/src/runtime/mgcscavenge.go:389 +0x53 fp=0xc000067fa0 sp=0xc000067f70 pc=0x496ed3
runtime.bgscavenge(0x0?)
	/usr/lib/go-1.19rc2/src/runtime/mgcscavenge.go:617 +0x45 fp=0xc000067fc8 sp=0xc000067fa0 pc=0x4974c5
runtime.gcenable.func2()
	/usr/lib/go-1.19rc2/src/runtime/mgc.go:179 +0x26 fp=0xc000067fe0 sp=0xc000067fc8 pc=0x48da46
runtime.goexit()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc000067fe8 sp=0xc000067fe0 pc=0x4db1a1
created by runtime.gcenable
	/usr/lib/go-1.19rc2/src/runtime/mgc.go:179 +0xaa

goroutine 5 [finalizer wait]:
runtime.gopark(0x89b760?, 0xc000007860?, 0x0?, 0x0?, 0xc000066770?)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:363 +0xd6 fp=0xc000066628 sp=0xc000066608 pc=0x4adbf6
runtime.goparkunlock(...)
	/usr/lib/go-1.19rc2/src/runtime/proc.go:369
runtime.runfinq()
	/usr/lib/go-1.19rc2/src/runtime/mfinal.go:180 +0x10f fp=0xc0000667e0 sp=0xc000066628 pc=0x48cbaf
runtime.goexit()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc0000667e8 sp=0xc0000667e0 pc=0x4db1a1
created by runtime.createfing
	/usr/lib/go-1.19rc2/src/runtime/mfinal.go:157 +0x45

goroutine 6 [runnable]:
regexp.(*inputString).step(0xc0000ba080?, 0x0?)
	/usr/lib/go-1.19rc2/src/regexp/regexp.go:391 +0x8d fp=0xc00007ad48 sp=0xc00007ad40 pc=0x5663cd
regexp.(*Regexp).tryBacktrack(0xc0000001e0, 0xc0000ba000, {0x5cdc08?, 0xc0000ba080}, 0x2?, 0x0?)
	/usr/lib/go-1.19rc2/src/regexp/backtrack.go:227 +0xb38 fp=0xc00007ae08 sp=0xc00007ad48 pc=0x55f078
regexp.(*Regexp).backtrack(0xc0000001e0, {0x0, 0x0, 0x0}, {0x59e16e, 0x3}, 0x0, 0x0?, {0x8c9d00, 0x0, ...})
	/usr/lib/go-1.19rc2/src/regexp/backtrack.go:353 +0x325 fp=0xc00007ae88 sp=0xc00007ae08 pc=0x55f5a5
regexp.(*Regexp).doExecute(0xc0000001e0?, {0x0?, 0x0}, {0x0, 0x0, 0x0}, {0x59e16e, 0x3}, 0x0?, 0x0, ...)
	/usr/lib/go-1.19rc2/src/regexp/exec.go:535 +0x272 fp=0xc00007af38 sp=0xc00007ae88 pc=0x561fd2
regexp.(*Regexp).doMatch(...)
	/usr/lib/go-1.19rc2/src/regexp/exec.go:514
regexp.(*Regexp).MatchString(...)
	/usr/lib/go-1.19rc2/src/regexp/regexp.go:533
main.mainLoop({0x5cda38, 0xc000090040})
	/home/dims/junk/plugin.go:74 +0x9e fp=0xc00007afc0 sp=0xc00007af38 pc=0x56c21e
main.main.func1()
	/home/dims/junk/plugin.go:40 +0x2a fp=0xc00007afe0 sp=0xc00007afc0 pc=0x56bfea
runtime.goexit()
	/usr/lib/go-1.19rc2/src/runtime/asm_amd64.s:1594 +0x1 fp=0xc00007afe8 sp=0xc00007afe0 pc=0x4db1a1
created by main.main
	/home/dims/junk/plugin.go:40 +0x85
exit status 2

@liggitt
Copy link
Contributor Author

liggitt commented Jul 21, 2022

sure, updated in the description

@dims
Copy link

dims commented Jul 21, 2022

@cherrymui Note that this same sample code works fine on my m1 macbook pro

[dims@dims-m1-7728 16:30] ~/junk ⟩ go version
go version go1.19rc2 darwin/arm64
[dims@dims-m1-7728 16:30] ~/junk ⟩ uname -a
Darwin dims-m1-7728.local 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:46:32 PDT 2022; root:xnu-8020.101.4~15/RELEASE_ARM64_T6000 arm64
[dims@dims-m1-7728 16:30] ~/junk ⟩ go version
go version go1.19rc2 darwin/arm64
[dims@dims-m1-7728 16:30] ~/junk ⟩ go build -buildmode=plugin ./plugin.go && go run ./plugin.go
mainLoop
pluginLoop
mainLoopPluginEval

@cherrymui
Copy link
Member

Thanks. It seems that both the main executable and the plugin have the function regexp.(*Regexp).tryBacktrack, but they are compiled slightly differently and the stack frame size is different. The runtime uses one's stack frame size to unwind the stack, while the frame actually on the stack is from the other.

Still looking into why backtrack from the plugin calls tryBacktrack from the main executable, and why the runtime uses wrong information...

@liggitt
Copy link
Contributor Author

liggitt commented Jul 21, 2022

while the investigation is going on, can this be added to the 1.19 milestone for visibility (ideally as a release-blocker)?

@liggitt
Copy link
Contributor Author

liggitt commented Jul 21, 2022

just as @dims could not reproduce on an M1 darwin machine, I couldn't reproduce on an darwin/amd64 machine, only a linux/amd64 machine

@cherrymui
Copy link
Member

could not reproduce on an M1 darwin machine, I couldn't reproduce on an darwin/amd64 machine, only a linux/amd64 machine

Yes, this bug depends on compiler and architecture details, and also how the dynamic linker resolves symbols, so it is very system dependent.

I think I understand the problem, will send a CL soon. Thanks.

@bboreham
Copy link
Contributor

they are compiled slightly differently

Can you clarify how the caller and plugin are compiled differently? Do you mean plugin mode is causing the difference?

@cherrymui
Copy link
Member

cherrymui commented Jul 21, 2022

The plugin needs to be position independent code, whereas the main executable doesn't. This causes slight differences in code generation, e.g. the use of GOT, TLS model, etc.

@gopherbot
Copy link

Change https://go.dev/cl/418960 mentions this issue: cmd/compile: make jump table symbol local

@dims
Copy link

dims commented Jul 21, 2022

@cherrymui sweeeeetttt! the change https://go.dev/cl/418960 fixed the original problem we had in kubernetes/kubernetes#111297

@toothrot toothrot added the NeedsFix The path to resolution is known, but the work has not been done. label Jul 22, 2022
@toothrot toothrot added this to the Backlog milestone Jul 22, 2022
@dims
Copy link

dims commented Jul 22, 2022

@cherrymui @toothrot can we please add this in 1.19?

@liggitt
Copy link
Contributor Author

liggitt commented Jul 22, 2022

@gopherbot please consider this for backport to 1.19, it's a regression.

@gopherbot
Copy link

Backport issue(s) opened: #54010 (for 1.19).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases.

@cherrymui
Copy link
Member

We don't need backport. Go 1.19 hasn't been released, and the tree is not open for 1.20 development. Go 1.19 will be cut on the main branch, which includes the CL above.

@liggitt
Copy link
Contributor Author

liggitt commented Jul 22, 2022

ah, my mistake, I didn't realize master kept getting merged to the 1.19 branch, thanks!

@liggitt
Copy link
Contributor Author

liggitt commented Jul 22, 2022

I don't have access to do so, but feel free to close #54010

@dmitshur dmitshur modified the milestones: Backlog, Go1.19 Jul 23, 2022
jproberts pushed a commit to jproberts/go that referenced this issue Aug 10, 2022
When using plugins, if the plugin and the main executable both
have the same function, and if it uses jump table, currently the
jump table symbol have the same name so it will be deduplicated by
the dynamic linker. This causes a function in the plugin may (in
the middle of the function) jump to the function with the same name
in the main executable (or vice versa). But the function may be
compiled slightly differently, because the plugin needs to be PIC.
Jumping from the middle of one function to the other will not work.
Avoid this problem by marking the jump table symbol local to a DSO.

Fixes golang#53989.

Change-Id: I2b573b9dfc22401c8a09ffe9b9ea8bb83d3700ca
Reviewed-on: https://go-review.googlesource.com/c/go/+/418960
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
@golang golang locked and limited conversation to collaborators Jul 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

7 participants