Skip to content

runtime: checkptr doesn't validate unsafe.Add function calls #74431

Open
@fxrlv

Description

@fxrlv

Go version

go version go1.24.4 darwin/arm64

Output of go env in your module/workspace:

AR='ar'
CC='cc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='c++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/fxrlv/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/fxrlv/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/mg/1l0261p97kzflrmx68mm4z7c0000gn/T/go-build2006285917=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/tmp/checkptr/go.mod'
GOMODCACHE='/Users/fxrlv/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/fxrlv/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.24.4/libexec'
GOSUMDB='sum.golang.org'
GOTELEMETRY='on'
GOTELEMETRYDIR='/Users/fxrlv/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.24.4/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

There is an inconsistency in how the checkptr runtime check validates pointer arithmetic.

The issue is that checkptr validates manual pointer arithmetic using uintptr conversions but does not validate the unsafe.Add function, which can perform equivalent potentially unsafe operations.

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	data := make([]byte, 10)

	// This triggers checkptr validation and can panic with:
	// "fatal error: checkptr: pointer arithmetic result points to invalid allocation"
	manualArithmetic := func(offset int) *byte {
		return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(unsafe.SliceData(data))) + uintptr(offset)))
	}

	// This does NOT trigger checkptr validation, even with equivalent dangerous operations
	unsafeAdd := func(offset int) *byte {
		return (*byte)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(data)), offset))
	}

	// Both can be equally dangerous when offset >= len(data) or offset < 0
	a := unsafeAdd(10)        // No checkptr validation
	b := manualArithmetic(10) // May trigger checkptr panic

	fmt.Println(a)
	fmt.Println(b)
}
$ go run -race main.go
fatal error: checkptr: pointer arithmetic result points to invalid allocation

goroutine 1 gp=0xc0000021c0 m=0 mp=0x100c056e0 [running]:
runtime.throw({0x100b0ac29?, 0x100b3e520?})
        /opt/homebrew/Cellar/go/1.24.4/libexec/src/runtime/panic.go:1101 +0x38 fp=0xc000187ea0 sp=0xc000187e70 pc=0x100ab5b68
runtime.checkptrArithmetic(0x100a56ec0?, {0xc000187f30, 0x1, 0x0?})
        /opt/homebrew/Cellar/go/1.24.4/libexec/src/runtime/checkptr.go:69 +0xa8 fp=0xc000187ed0 sp=0xc000187ea0 pc=0x100a58238
main.main.func1(...)
        /tmp/checkptr/main.go:14
main.main()
        /tmp/checkptr/main.go:24 +0x70 fp=0xc000187f40 sp=0xc000187ed0 pc=0x100b01550
runtime.main()
        /opt/homebrew/Cellar/go/1.24.4/libexec/src/runtime/proc.go:283 +0x284 fp=0xc000187fd0 sp=0xc000187f40 pc=0x100a84ef4
runtime.goexit({})
        /opt/homebrew/Cellar/go/1.24.4/libexec/src/runtime/asm_arm64.s:1223 +0x4 fp=0xc000187fd0 sp=0xc000187fd0 pc=0x100abc744

What did you see happen?

  • unsafe.Add calls: No validation, no panics
  • Manual pointer arithmetic: checkptr validates and panics with "pointer arithmetic result points to invalid allocation"

What did you expect to see?

Both manual pointer arithmetic and unsafe.Add should receive the same level of validation from checkptr. If manual uintptr arithmetic is checked for validity, then unsafe.Add calls should also be validated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.compiler/runtimeIssues related to the Go compiler and/or runtime.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions