Skip to content

cmd/compile: out-of-bounds panic with uint32 conversion and modulus operation in Go 1.22.0 on arm64 #66066

@jnoxon

Description

@jnoxon

Go version

go version go1.22.0 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/jeff/Library/Caches/go-build'
GOENV='/Users/jeff/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/jeff/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/jeff/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/jeff/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.darwin-arm64'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/jeff/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.darwin-arm64/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.0'
GCCGO='gccgo'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/jeff/go/src/github.com/spyderbat/crash-example/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/h8/9kxv3svd2bx_6hg8pxcg_skh0000gn/T/go-build1296351590=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

On linux/arm64 and darwin/arm64, with the latest compiler, this program crashes:

package main

import "fmt"

/*
This code demonstrates an out-of-bounds panic that occurs on go1.22.0 on linux/arm64 and darwin/arm64.

It does not panic on go1.21.6 on arm64, or on go1.22.0 on amd64.
It also does not panic when built with -gcflags="-N -l" on go1.22.0 on arm64.
*/

// if this function is inlined, the code will not panic
//
//go:noinline
func u32max() uint32 {
	// if bit 32 is clear, the code will not panic
	x := int64(1<<32 - 1)
	return uint32(x)
}

func main() {
	arr := []int{1, 2, 3}

	fmt.Printf("u32max: %d\n", u32max())
	fmt.Printf("len(arr): %d\n", len(arr))
	fmt.Printf("u32max mod len(arr): %d\n", u32max()%uint32(len(arr)))

	_ = arr[u32max()%uint32(len(arr))]
}

What did you see happen?

go run main.go

u32max: 4294967295
len(arr): 3
u32max mod len(arr): 0
panic: runtime error: index out of range [-4294967296]

goroutine 1 [running]:
main.main()
	/Users/jeff/go/src/github.com/jnoxon/crash-example/main.go:28 +0x150
exit status 2

What did you expect to see?

It should run the same as it does without optimizations:

go run -gcflags="-N -l" main.go

u32max: 4294967295
len(arr): 3
u32max mod len(arr): 0

Metadata

Metadata

Assignees

Labels

FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.arch-arm64compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions