go: cmd/compile: bad inlining tree emitted for function literal
What version of Go are you using (go version
)?
$ go version go version devel go1.17-8b0901fd32 Tue May 18 07:50:25 2021 +0000 linux/amd64
Does this issue reproduce with the latest release?
Only on 1.17 / tip – this problem is not present in 1.16.
What operating system and processor architecture are you using (go env
)?
linux/amd64
What did you do?
Run this program: https://play.golang.org/p/VZWvwkvYUGx
What did you expect to see?
In 1.16 you get a crash on a nil pointer, e.g.
$ go run repro.go
begin main
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4a2245]
goroutine 1 [running]:
main.WEA.func1(0x0)
/tmp/repro.go:17 +0x5
main.(*CM).NewA(0xc0000eef40, 0x0, 0x0, 0x4c761f, 0x3, 0x0, 0xc0000eeed0, 0x2, 0x2, 0xb, ...)
/tmp/repro.go:30 +0x42
main.(*R).CA(0xc0000eef48, 0x0, 0x0, 0x4c761f, 0x3, 0x0, 0x0, 0xb, 0x0)
/tmp/repro.go:37 +0xd1
main.main()
/tmp/repro.go:52 +0xc5
exit status 2
thanm@cetina:/tmp$
What did you see instead?
Program gets an infinite loop in traceback:
begin main
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x487f00]
goroutine 1 [running]:
main.WEA(...)
/tmp/repro.go:17
main.WEA(...)
/tmp/repro.go:17
main.WEA(...)
/tmp/repro.go:17
main.WEA(...)
/tmp/repro.go:17
<repeats>
The problem sees to be in the runtime’s traceback handling of inlining – at the point of the fault we are at
Dump of assembler code for function main.(*R).CA.func1:
=> 0x0000000000487f00 <+0>: movb $0x1,(%rax)
0x0000000000487f03 <+3>: retq
The inlining tree for this function (from go build -gcflags=-d=pctab=pctoinline) looks like
-- inlining tree for "".(*R).CA.func1:
0 | -1 | "".WEA (/tmp/repro.go:37:39) pc=0
The problem here is that the traceback code is trying to “back up” an instruction when landing on 0x0000000000487f00 to recover the parent PC (runtime code here), but this winds up hitting the same instruction, hence we never get out of the loop.
I’m tentatively marking this as a compiler bug, can be retitled if it turns out there are other components involved.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 20 (17 by maintainers)
Commits related to this issue
- cmd/compile/internal/inline: revise closure inl position fix This patch revises the fix for issue 46234, fixing a bug that was accidentally introduced by CL 320913. When inlining a chunk of code with... — committed to golang/go by thanm 3 years ago
- cmd/compile/internal/noder: fix inlined function literal positions When inlining function calls, we rewrite the position information on all of the nodes to keep track of the inlining context. This is... — committed to golang/go by mdempsky 2 years ago
- cmd/compile/internal/noder: fix inlined function literal positions When inlining function calls, we rewrite the position information on all of the nodes to keep track of the inlining context. This is... — committed to rajbarik/go by mdempsky 2 years ago
It shows up in the dump. For example in this code:
the calls to WEA() get inlined. In the dump you can see this in the second column:
Note the “0” for the instruction at 00059.
At least that’s how I’m reading it; hopefully I am not off base.
@cherrymui I was able to confirm that the loop does go infinite. We only check the
n < max
condition at the top-level, whereas the inner loop for handling PCDATA_InlTreeIndex goes until it finds a negative value (which never happens with a cycle).