Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/runtime/malloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2483,3 +2483,29 @@ func redZoneSize(userSize uintptr) uintptr {
return 16 << 7
}
}

// actualSize computes the user allocation size from the total size including redzone.
// Refer to the implementation of the compiler-rt.
func actualSize(allocSize uintptr) uintptr {
if !asanenabled{
return allocSize
}
switch {
case allocSize > (1<<16) - 1024 + 16<<6:
return allocSize - 16<<7
case allocSize > (1<<15) - 512 + 16<<5:
return allocSize - 16<<6
case allocSize > (1<<14) - 256 + 16<<4:
return allocSize - 16<<5
case allocSize > 4096 - 128 + 16<<3:
return allocSize - 16<<4
case allocSize > 512 - 64 + 16<<2:
return allocSize - 16<<3
case allocSize > 128 - 32 + 16<<1:
return allocSize - 16<<2
case allocSize > 64 - 16 + 16<<0:
return allocSize - 16<<1
default:
return allocSize - 16<<0
}
}
22 changes: 16 additions & 6 deletions src/runtime/mbitmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,12 @@ func (span *mspan) writeHeapBitsSmall(x, dataSize uintptr, typ *_type) (scanSize
// The objects here are always really small, so a single load is sufficient.
src0 := readUintptr(getGCMask(typ))

// When ASAN is enabled, a redzone is appended to the data, and the redzone would affect
// bitmap calculation by being incorrectly marked as pointers.
srcDataSize := dataSize
if asanenabled {
dataSize = actualSize(srcDataSize)
}
// Create repetitions of the bitmap if we have a small slice backing store.
src := src0
if typ.Size_ == goarch.PtrSize {
Expand All @@ -635,21 +641,19 @@ func (span *mspan) writeHeapBitsSmall(x, dataSize uintptr, typ *_type) (scanSize
// N.B. We rely on dataSize being an exact multiple of the type size.
// The alternative is to be defensive and mask out src to the length
// of dataSize. The purpose is to save on one additional masking operation.
if doubleCheckHeapSetType && !asanenabled && dataSize%typ.Size_ != 0 {
if doubleCheckHeapSetType && dataSize%typ.Size_ != 0 {
throw("runtime: (*mspan).writeHeapBitsSmall: dataSize is not a multiple of typ.Size_")
}
scanSize = typ.PtrBytes
for i := typ.Size_; i < dataSize; i += typ.Size_ {
src |= src0 << (i / goarch.PtrSize)
scanSize += typ.Size_
}
if asanenabled {
// Mask src down to dataSize. dataSize is going to be a strange size because of
// the redzone required for allocations when asan is enabled.
src &= (1 << (dataSize / goarch.PtrSize)) - 1
}
}

if asanenabled {
scanSize += srcDataSize - dataSize
}
// Since we're never writing more than one uintptr's worth of bits, we're either going
// to do one or two writes.
dstBase, _ := spanHeapBitsRange(span.base(), pageSize, span.elemsize)
Expand Down Expand Up @@ -810,6 +814,9 @@ func doubleCheckHeapType(x, dataSize uintptr, gctyp *_type, header **_type, span
maxIterBytes := span.elemsize
if header == nil {
maxIterBytes = dataSize
if asanenabled {
maxIterBytes = actualSize(dataSize)
}
}
off := alignUp(uintptr(cheaprand())%dataSize, goarch.PtrSize)
size := dataSize - off
Expand All @@ -836,6 +843,9 @@ func doubleCheckHeapPointers(x, dataSize uintptr, typ *_type, header **_type, sp
maxIterBytes := span.elemsize
if header == nil {
maxIterBytes = dataSize
if asanenabled {
maxIterBytes = actualSize(dataSize)
}
}
bad := false
for i := uintptr(0); i < maxIterBytes; i += goarch.PtrSize {
Expand Down