Skip to content

runtime: ASAN redzone incorrectly marked as pointers in bitmap #80136

Description

@qinlonglong123

Go version

go version go1.27-devel_c996ed1abc

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-fstack-protector-all'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE='auto'
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN='/opt/go_workpace/bin'
GOCACHE='/usr1/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2984481877=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD=''
GOMODCACHE='/opt/go_workpace/pkg/mod'
GONOPROXY=''
GONOSUMDB='*'
GOOS='linux'
GOPACKAGESDRIVER=''
GOPATH='/opt/go_workpace'
GOPRIVATE=''
GOPROXY=''
GOROOT='/root/qll/go/'
GOSUMDB='off'
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/root/qll/go/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.27-devel_c996ed1abc Tue Jun 23 20:49:23 2026 -0700'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

runtime: ASAN redzone incorrectly marked as pointers

Problem

When ASAN is enabled and redzone >= typ.Size_ , the writeHeapBitsSmall function uses dataSize (which includes the ASAN redzone) to calculate the bitmap pointer bits mask. This causes the redzone region to be incorrectly marked as pointers in the heap bitmap.

This leads to failures in doubleCheckHeapPointers and doubleCheckHeapPointersInterior, which throw "heapSetType: pointer entry not correct".

Root Cause

In writeHeapBitsSmall:

if typ.Size_ == goarch.PtrSize {
    src = (1 << (dataSize / goarch.PtrSize)) - 1  // dataSize includes ASAN redzone
    scanSize = dataSize
}

When ASAN is enabled, dataSize = userSize + redZoneSize. Using this inflated size causes the bitmap to mark more bytes as pointers than actually exist in the user data.

Detailed Description with Example

For example, consider the following code:

package main

import (
	"runtime"
)

type MySmallCustomType struct {
	P0 *int
}

var (
	objCustom []MySmallCustomType
)

func main() {
	runtime.GOMAXPROCS(1)
	objCustom = make([]MySmallCustomType, 2)
	println(objCustom)
	runtime.KeepAlive(objCustom)
}

With ASAN enabled, objCustom itself occupies 16 bytes (2 elements × 8 bytes per pointer), and ASAN adds a 16-byte redzone. When entering writeHeapBitsSmall, it takes the branch:

if typ.Size_ == goarch.PtrSize {
    src = (1 << (dataSize / goarch.PtrSize)) - 1
    scanSize = dataSize
}

At this point, dataSize is 32 bytes (16 bytes user data + 16 bytes ASAN redzone). The original logic marks the ASAN redzone's 16 bytes as pointers in the bitmap as well, which is incorrect.

What did you see happen?

With ASAN enabled and typ.Size_ == goarch.PtrSize, The heap bitmap incorrectly marked the ASAN redzone region as pointers.

What did you expect to see?

The heap bitmap should only mark the actual user data region as pointers, excluding the ASAN redzone. The bitmap should correctly reflect the pointer layout of the allocated object without including the poisoned redzone bytes that ASAN inserts for overflow detection.

Metadata

Metadata

Labels

NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions