-
Notifications
You must be signed in to change notification settings - Fork 18k
hash/crc32: panic on arm64 with go1.21.0 when indexing slice #62131
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
Smaller examplepackage main
import "hash/crc32"
func main() {
colors := []string{"ffd179", "b786d2", "bed3f4"}
// has is uint32(754903878), but panic occures only during crc32 call
// and not, when you set this value explicitely
hash := crc32.ChecksumIEEE([]byte("jHjDiYOWTOS53K9t3XbOU7QXAwD3"))
index := hash % uint32(3)
_ = colors[index] // PANIC: index out of range -4294967296
return
} The magic uint64 number More contextduring execution, around
x0: After substracting uint32 type is ignored here. Everywhere. Panics on |
According to docs & playground proof:
Following call makes sets return ^ieeeUpdate(^crc, p) // hash/crc32.archUpdateIEEE mvn x0 x0 |
CC @golang/security. |
No dependencies example
|
Since you can reproduce the problem in assembly, it seems likely that this is a compiler or runtime change. Can you build the Go repo from source and use |
(attn @golang/compiler @golang/arm) |
Simple reproducer:
Looks like there is a missing |
This looks like https://go-review.googlesource.com/c/go/+/427454 |
Looks like the |
I've hacked up a change that fixes all the rules to preserve the semantics of the upper 32 bits. For example, when rewriting I worry other architectures have the same issue, as lots of those were started by copying the arm64 port. I will investigate. |
@gopherbot please open a backport to 1.21. |
Backport issue(s) opened: #62143 (for 1.21). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
Change https://go.dev/cl/520916 mentions this issue: |
Thanks for the fix! @randall77
Does it look like CL 427454 is still correct if we can hold this for all 32-bit rewrite rules? The revert is fine, I just wonder if we can redo this work after your fix in 1.22. |
CL 427454 is not reverted in the tip branch. I think Keith's fix is the right direction. |
When rewriting, for example, MSUBW, we need to ensure that the result has its 32 top bits zeroed. That's what the instruction is spec'd to do. Normally, we'd only use MSUBW for computations on 32-bit values, and as such the top 32 bits aren't normally used. But some situations, like if we cast the result to a uint64, the top 32 bits do matter. This comes up in 62131 because we have a rule saying, MOVWUreg applied to a MSUBW is unnecessary, as the arg to MOVWUreg already has zeroed top 32 bits. But if MSUBW is later rewritten to another op that doesn't zero the top 32 bits (SUB, probably), getting rid of the MOVWUreg earlier causes a problem. So change rewrite rules to always maintain the top 32 bits as zero if the instruction is spec'd to provide that. We need to introduce a few *W operations to make that happen. Fixes golang#62131 Change-Id: If3d160821e285fd7454746b735a243671bff8894 Reviewed-on: https://go-review.googlesource.com/c/go/+/520916 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@google.com>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
This code panics on go 1.21 on arm64 but runs fine on other platforms or go 1.20 arm64:
What did you expect to see?
A string printed
What did you see instead?
The text was updated successfully, but these errors were encountered: