-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/go: miscompilation of codependent global var
assigments in go1.12
#30977
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
Comments
For completeness here is the actual full type which is slightly more complex than I let on above: // Version represents a semver compatible version
type Version struct {
Major uint64
Minor uint64
Patch uint64
Pre []PRVersion
Build []string //No Precedence
} |
ping @bradfitz PTAL |
var
assigments in go1.12var
assigments in go1.12
Tentatively milestoning as 1.12 since it appears to be a recent regression. |
Thanks! |
Thanks for the bug report! If you/anyone wants to try to minimize further, setting |
FWIW I just tested on The |
|
Interesting. I'll take a careful look.
On ARM64, many address operations are split into multiple instructions, as it cannot load a 64-bit address in a single instruction, and currently objdump is not smart enough to recombine them. |
The same "volatile" stack temporary is used in two stores, both with write barriers. I think we don't generate this before, so the write barrier pass doesn't handle this case. Now we optimize |
My bisect fingered 6c631ae "cmd/compile: in wasm, allocate approximately right number of locals for functions", but that doesn't pass the sniff test and I couldn't confirm manually. I suspect that is a misbisect (I probably got distracted and failed to test some rev but still entered a result). I've scripted it this time and |
It's not done but I really have to run. It's narrowed it down so far to:
At this point I'd probably guess at 2578ac5 "cmd/compile: move argument stack construction to SSA generation". |
Change https://golang.org/cl/168677 mentions this issue: |
@ijc thanks for the bisects. I think CL https://golang.org/cl/168677 should fix this. You don't have to do more. |
https://play.golang.org/p/5DpJ673vnSJ On tip (700e969), this fails quite reliably. |
@gopherbot please backport this to Go 1.12. |
Backport issue(s) opened: #30996 (for 1.12). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases. |
Change https://golang.org/cl/168817 mentions this issue: |
The bisect was automated so I may as well report the result which was that it blamed 2578ac5 "cmd/compile: move argument stack construction to SSA generation", which seems legit.
|
@katiehockman and @andybons about the 1.12.2 release. (I don't know the answer.) |
We try to do minor point releases on the first of the month, so the next one would be April 1 ideally. |
Thanks @andybons that should help us figure out what to do. |
@ALTree I see the milestone was changed from 1.12.2 to 1.13 Is a separate tracking-issue needed to track it for Go 1.12.2? |
@thaJeztah That's #30996. It was opened a week ago, and that's the reason I moved this one to 1.13. |
oh! I see now; I overlooked the bot's comment as it's usually commenting related to changes in Gerrit. Apologies; still getting the hang of the bots and flow in this repository 🤗 |
@thaJeztah No problem. Feel free to
if you are worried we may forget it before the 1.12.2 release gets finalized. It happened once, unfortunately. The cherry-picked fix for an issues was ready, but it didn't get merged and the release scripts ignored it. |
…ting write barrier call It is possible that a "volatile" value (one that can be clobbered by preparing args of a call) to be used in multiple write barrier calls. We used to copy the volatile value right before each call. But this doesn't work if the value is used the second time, after the first call where it is already clobbered. Copy it before emitting any call. Updates #30977. Fixes #30996. Change-Id: Iedcc91ad848d5ded547bf37a8359c125d32e994c Reviewed-on: https://go-review.googlesource.com/c/go/+/168677 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> (cherry picked from commit f23c601) Reviewed-on: https://go-review.googlesource.com/c/go/+/168817 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
It reproduces with go 1.12.1 so I believe yes. I downloaded it from https://dl.google.com/go/go1.12.1.linux-amd64.tar.gz
I've also reproduced on
darwin/amd64
from https://golang.org/doc/install?download=go1.12.1.darwin-amd64.pkg:What operating system and processor architecture are you using (
go env
)?linux/amd64 (Debian).
go env
Output on linux/amd64I have also reproduced on darwin/amd64:
go env
Output on darwin/amd64What did you do?
I have a program which includes:
The types are
semver.Version
which is a struct with a handful of fields (Major
,Minor
etc).I am seeing corruption of
VersionLatest
where the major field is824638865200
(always that number, AFAICS) after init and not0
.Version0_2_0
is never corrupted.I have narrowed it down to this minimal case: go1.12-initvar-miscompile.zip
Note that the test program includes a massive bunch of anonymous imports, these seem to be necessary to trigger the runtime/gc load and cause the issue (they are derived from all the vendoring in my actual project which have
init()
functions). Trying to minimise the set of imports is non-linear (since the issue is non-deterministic AFAICT) and also reduces the probability of the issue occurring. I got it down to a dozen or so imports and a 1/10,000 incidence, since it is much easier to reproduce with the larger import set that is what I included here.What did you expect to see?
On success
VersionLatest
is"0.2.0"
.What did you see instead?
It is corrupted to
"824638766896.2.0"
.Analysis
After the call to
semver.MustParse
there is aruntime.writeBarrier
slow path:The issue occurs precisely when this jump is taken and is during this sequence:
On go1.11.4 the same code is compiled differently and the second copy is
memcpy(VersionLatest, Version0_2_0)
instead which does not use the corrupted stack copyBTW, the code pattern is the same in the fast pass, but that lacks the call to
runtime.typedmemmove
which overwrites the stack value, thus the issue only occurs if we manager to hit the slow path.Full
go tool objdump -s '^main.init.ializers'
Output for go 1.12.1 compilationThe text was updated successfully, but these errors were encountered: